1 2 package JSci.maths.matrices; 3 4 import JSci.GlobalSettings; 5 import JSci.maths.ArrayMath; 6 import JSci.maths.ExtraMath; 7 import JSci.maths.LinearMath; 8 import JSci.maths.MaximumIterationsExceededException; 9 import JSci.maths.Mapping; 10 import JSci.maths.vectors.AbstractDoubleVector; 11 import JSci.maths.groups.AbelianGroup; 12 import JSci.maths.algebras.*; 13 import JSci.maths.fields.*; 14 15 20 public abstract class AbstractDoubleSquareMatrix extends AbstractDoubleMatrix implements SquareMatrix { 21 protected transient AbstractDoubleSquareMatrix[] LU; 22 protected transient int[] LUpivot; 23 26 protected AbstractDoubleSquareMatrix(final int size) { 27 super(size, size); 28 } 29 33 public AbstractIntegerMatrix toIntegerMatrix() { 34 final int ans[][]=new int[numRows][numCols]; 35 for(int i=0;i<numRows;i++) { 36 for(int j=0;j<numCols;j++) 37 ans[i][j]=Math.round((float)getElement(i,j)); 38 } 39 return new IntegerSquareMatrix(ans); 40 } 41 45 public AbstractComplexMatrix toComplexMatrix() { 46 ComplexSquareMatrix cm = new ComplexSquareMatrix(numRows); 47 for(int i=0;i<numRows;i++) { 48 for(int j=0;j<numCols;j++) 49 cm.setElement(i, j, getElement(i, j), 0.0); 50 } 51 return cm; 52 } 53 56 public boolean isSymmetric() { 57 return this.equals(this.transpose()); 58 } 59 62 public boolean isUnitary() { 63 return this.multiply(this.transpose()).equals(DoubleDiagonalMatrix.identity(numRows)); 64 } 65 68 public double det() { 69 if(numRows==2) { 70 return getElement(0,0)*getElement(1,1)-getElement(0,1)*getElement(1,0); 71 } else { 72 final AbstractDoubleSquareMatrix lu[]=this.luDecompose(null); 73 double det=lu[1].getElement(0,0); 74 for(int i=1;i<numRows;i++) 75 det*=lu[1].getElement(i,i); 76 return det*LUpivot[numRows]; 77 } 78 } 79 82 public double trace() { 83 double result = getElement(0,0); 84 for(int i=1;i<numRows;i++) 85 result += getElement(i,i); 86 return result; 87 } 88 92 public double operatorNorm() throws MaximumIterationsExceededException { 93 return Math.sqrt(ArrayMath.max(LinearMath.eigenvalueSolveSymmetric((AbstractDoubleSquareMatrix)(this.transpose().multiply(this))))); 94 } 95 96 100 103 public AbelianGroup.Member negate() { 104 final double array[][]=new double[numRows][numCols]; 105 for(int i=0;i<numRows;i++) { 106 array[i][0] = -getElement(i,0); 107 for(int j=1;j<numCols;j++) 108 array[i][j] = -getElement(i,j); 109 } 110 return new DoubleSquareMatrix(array); 111 } 112 113 115 120 public final AbstractDoubleMatrix add(final AbstractDoubleMatrix m) { 121 if(m instanceof AbstractDoubleSquareMatrix) 122 return add((AbstractDoubleSquareMatrix)m); 123 else if(numRows == m.rows() && numCols == m.columns()) 124 return add(new SquareMatrixAdaptor(m)); 125 else 126 throw new MatrixDimensionException("Matrices are different sizes."); 127 } 128 133 public AbstractDoubleSquareMatrix add(final AbstractDoubleSquareMatrix m) { 134 if(numRows==m.rows() && numCols==m.columns()) { 135 final double array[][]=new double[numRows][numCols]; 136 for(int i=0;i<numRows;i++) { 137 array[i][0] = getElement(i,0)+m.getElement(i,0); 138 for(int j=1;j<numCols;j++) 139 array[i][j] = getElement(i,j)+m.getElement(i,j); 140 } 141 return new DoubleSquareMatrix(array); 142 } else { 143 throw new MatrixDimensionException("Matrices are different sizes."); 144 } 145 } 146 147 149 154 public final AbstractDoubleMatrix subtract(final AbstractDoubleMatrix m) { 155 if(m instanceof AbstractDoubleSquareMatrix) 156 return subtract((AbstractDoubleSquareMatrix)m); 157 else if(numRows == m.rows() && numCols == m.columns()) 158 return subtract(new SquareMatrixAdaptor(m)); 159 else 160 throw new MatrixDimensionException("Matrices are different sizes."); 161 } 162 167 public AbstractDoubleSquareMatrix subtract(final AbstractDoubleSquareMatrix m) { 168 if(numRows==m.rows() && numCols==m.columns()) { 169 final double array[][]=new double[numRows][numCols]; 170 for(int i=0;i<numRows;i++) { 171 array[i][0] = getElement(i,0)-m.getElement(i,0); 172 for(int j=1;j<numCols;j++) 173 array[i][j] = getElement(i,j)-m.getElement(i,j); 174 } 175 return new DoubleSquareMatrix(array); 176 } else { 177 throw new MatrixDimensionException("Matrices are different sizes."); 178 } 179 } 180 181 183 188 public AbstractDoubleMatrix scalarMultiply(final double x) { 189 final double array[][]=new double[numRows][numCols]; 190 for(int i=0;i<numRows;i++) { 191 array[i][0] = x*getElement(i,0); 192 for(int j=1;j<numCols;j++) 193 array[i][j] = x*getElement(i,j); 194 } 195 return new DoubleSquareMatrix(array); 196 } 197 198 200 205 public AbstractDoubleMatrix scalarDivide(final double x) { 206 final double array[][]=new double[numRows][numCols]; 207 for(int i=0;i<numRows;i++) { 208 array[i][0] = getElement(i,0)/x; 209 for(int j=1;j<numCols;j++) 210 array[i][j] = getElement(i,j)/x; 211 } 212 return new DoubleSquareMatrix(array); 213 } 214 215 217 222 public final double scalarProduct(final AbstractDoubleMatrix m) { 223 if(m instanceof AbstractDoubleSquareMatrix) 224 return scalarProduct((AbstractDoubleSquareMatrix)m); 225 else if(numRows == m.rows() && numCols == m.columns()) 226 return scalarProduct(new SquareMatrixAdaptor(m)); 227 else 228 throw new MatrixDimensionException("Matrices are different sizes."); 229 } 230 235 public double scalarProduct(final AbstractDoubleSquareMatrix m) { 236 if(numRows==m.rows() && numCols==m.columns()) { 237 double ans = 0; 238 for(int i=0; i<numRows; i++) { 239 ans += getElement(i,0)*m.getElement(i,0); 240 for(int j=1; j<numCols; j++) 241 ans += getElement(i,j)*m.getElement(i,j); 242 } 243 return ans; 244 } else { 245 throw new MatrixDimensionException("Matrices are different sizes."); 246 } 247 } 248 249 251 256 public AbstractDoubleSquareMatrix multiply(final AbstractDoubleSquareMatrix m) { 257 if(numCols==m.rows()) { 258 final int mColumns = m.columns(); 259 final double array[][]=new double[numRows][mColumns]; 260 for(int j=0; j<numRows; j++) { 261 for(int k=0; k<mColumns; k++) { 262 array[j][k] = getElement(j,0)*m.getElement(0,k); 263 for(int n=1; n<numCols; n++) 264 array[j][k] += getElement(j,n)*m.getElement(n,k); 265 } 266 } 267 return new DoubleSquareMatrix(array); 268 } else { 269 throw new MatrixDimensionException("Incompatible matrices."); 270 } 271 } 272 273 275 278 public AbstractDoubleSquareMatrix directSum(final AbstractDoubleSquareMatrix m) { 279 final double array[][]=new double[numRows+m.numRows][numCols+m.numCols]; 280 for(int i=0;i<numRows;i++) { 281 for(int j=0;j<numCols;j++) 282 array[i][j] = getElement(i,j); 283 } 284 for(int i=0;i<m.numRows;i++) { 285 for(int j=0;j<m.numCols;j++) 286 array[i+numRows][j+numCols] = m.getElement(i,j); 287 } 288 return new DoubleSquareMatrix(array); 289 } 290 291 293 296 public AbstractDoubleSquareMatrix tensor(final AbstractDoubleSquareMatrix m) { 297 final double array[][]=new double[numRows*m.numRows][numCols*m.numCols]; 298 for(int i=0;i<numRows;i++) { 299 for(int j=0;j<numCols;j++) { 300 for(int k=0;k<m.numRows;j++) { 301 for(int l=0;l<m.numCols;l++) 302 array[i*m.numRows+k][j*m.numCols+l] = getElement(i,j)*m.getElement(k,l); 303 } 304 } 305 } 306 return new DoubleSquareMatrix(array); 307 } 308 309 311 315 public Matrix transpose() { 316 final double array[][]=new double[numCols][numRows]; 317 for(int i=0;i<numRows;i++) { 318 array[0][i] = getElement(i,0); 319 for(int j=1;j<numCols;j++) 320 array[j][i] = getElement(i,j); 321 } 322 return new DoubleSquareMatrix(array); 323 } 324 325 327 331 public AbstractDoubleSquareMatrix inverse() { 332 final int N=numRows; 333 final double arrayL[][]=new double[N][N]; 334 final double arrayU[][]=new double[N][N]; 335 final AbstractDoubleSquareMatrix lu[]=this.luDecompose(null); 336 arrayL[0][0]=1.0/lu[0].getElement(0,0); 337 arrayU[0][0]=1.0/lu[1].getElement(0,0); 338 for(int i=1;i<N;i++) { 339 arrayL[i][i]=1.0/lu[0].getElement(i,i); 340 arrayU[i][i]=1.0/lu[1].getElement(i,i); 341 } 342 for(int i=0;i<N-1;i++) { 343 for(int j=i+1;j<N;j++) { 344 double tmpL=0.0, tmpU=0.0; 345 for(int k=i;k<j;k++) { 346 tmpL-=lu[0].getElement(j,k)*arrayL[k][i]; 347 tmpU-=arrayU[i][k]*lu[1].getElement(k,j); 348 } 349 arrayL[j][i]=tmpL/lu[0].getElement(j,j); 350 arrayU[i][j]=tmpU/lu[1].getElement(j,j); 351 } 352 } 353 final double inv[][]=new double[N][N]; 355 for(int i=0;i<N;i++) { 356 for(int j=0;j<i;j++) { 357 for(int k=i;k<N;k++) 358 inv[i][LUpivot[j]]+=arrayU[i][k]*arrayL[k][j]; 359 } 360 for(int j=i;j<N;j++) { 361 for(int k=j;k<N;k++) 362 inv[i][LUpivot[j]]+=arrayU[i][k]*arrayL[k][j]; 363 } 364 } 365 return new DoubleSquareMatrix(inv); 366 } 367 368 370 379 public AbstractDoubleSquareMatrix[] luDecompose(int pivot[]) { 380 if(LU!=null) { 381 if(pivot!=null) 382 System.arraycopy(LUpivot,0,pivot,0,pivot.length); 383 return LU; 384 } 385 int pivotrow; 386 final int N=numRows; 387 final double arrayL[][]=new double[N][N]; 388 final double arrayU[][]=new double[N][N]; 389 if(pivot==null) 390 pivot=new int[N+1]; 391 for(int i=0;i<N;i++) 392 pivot[i]=i; 393 pivot[N]=1; 394 for(int j=0;j<N;j++) { 396 for(int i=0;i<j;i++) { 397 double tmp=getElement(pivot[i],j); 398 for(int k=0;k<i;k++) 399 tmp-=arrayU[i][k]*arrayU[k][j]; 400 arrayU[i][j]=tmp; 401 } 402 double max=0.0; 403 pivotrow=j; 404 for(int i=j;i<N;i++) { 405 double tmp=getElement(pivot[i],j); 406 for(int k=0;k<j;k++) 407 tmp-=arrayU[i][k]*arrayU[k][j]; 408 arrayU[i][j]=tmp; 409 tmp=Math.abs(tmp); 411 if(tmp>max) { 412 max=tmp; 413 pivotrow=i; 414 } 415 } 416 if(pivotrow!=j) { 418 double[] tmprow = arrayU[j]; 419 arrayU[j] = arrayU[pivotrow]; 420 arrayU[pivotrow] = tmprow; 421 int k=pivot[j]; 422 pivot[j]=pivot[pivotrow]; 423 pivot[pivotrow]=k; 424 pivot[N]=-pivot[N]; 426 } 427 double tmp=arrayU[j][j]; 429 for(int i=j+1;i<N;i++) 430 arrayU[i][j]/=tmp; 431 } 432 for(int j=0;j<N;j++) { 434 arrayL[j][j]=1.0; 435 for(int i=j+1;i<N;i++) { 436 arrayL[i][j]=arrayU[i][j]; 437 arrayU[i][j]=0.0; 438 } 439 } 440 LU=new AbstractDoubleSquareMatrix[2]; 441 LU[0]=new DoubleSquareMatrix(arrayL); 442 LU[1]=new DoubleSquareMatrix(arrayU); 443 LUpivot=new int[pivot.length]; 444 System.arraycopy(pivot,0,LUpivot,0,pivot.length); 445 return LU; 446 } 447 454 public AbstractDoubleSquareMatrix[] luDecompose() { 455 final int N=numRows; 456 final double arrayL[][]=new double[N][N]; 457 final double arrayU[][]=new double[N][N]; 458 for(int j=0;j<N;j++) { 460 for(int i=0;i<j;i++) { 461 double tmp=getElement(i,j); 462 for(int k=0;k<i;k++) 463 tmp-=arrayU[i][k]*arrayU[k][j]; 464 arrayU[i][j]=tmp; 465 } 466 for(int i=j;i<N;i++) { 467 double tmp=getElement(i,j); 468 for(int k=0;k<j;k++) 469 tmp-=arrayU[i][k]*arrayU[k][j]; 470 arrayU[i][j]=tmp; 471 } 472 double tmp=arrayU[j][j]; 474 for(int i=j+1;i<N;i++) 475 arrayU[i][j]/=tmp; 476 } 477 for(int j=0;j<N;j++) { 479 arrayL[j][j]=1.0; 480 for(int i=j+1;i<N;i++) { 481 arrayL[i][j]=arrayU[i][j]; 482 arrayU[i][j]=0.0; 483 } 484 } 485 AbstractDoubleSquareMatrix[] lu=new AbstractDoubleSquareMatrix[2]; 486 lu[0]=new DoubleSquareMatrix(arrayL); 487 lu[1]=new DoubleSquareMatrix(arrayU); 488 return lu; 489 } 490 491 493 499 public AbstractDoubleSquareMatrix[] choleskyDecompose() { 500 final int N=numRows; 501 final double arrayL[][]=new double[N][N]; 502 final double arrayU[][]=new double[N][N]; 503 double tmp=Math.sqrt(getElement(0,0)); 504 arrayL[0][0]=arrayU[0][0]=tmp; 505 for(int i=1;i<N;i++) 506 arrayL[i][0]=arrayU[0][i]=getElement(i,0)/tmp; 507 for(int j=1;j<N;j++) { 508 tmp=getElement(j,j); 509 for(int i=0;i<j;i++) 510 tmp-=arrayL[j][i]*arrayL[j][i]; 511 arrayL[j][j]=arrayU[j][j]=Math.sqrt(tmp); 512 for(int i=j+1;i<N;i++) { 513 tmp=getElement(i,j); 514 for(int k=0;k<i;k++) 515 tmp-=arrayL[j][k]*arrayU[k][i]; 516 arrayL[i][j]=arrayU[j][i]=tmp/arrayU[j][j]; 517 } 518 } 519 final AbstractDoubleSquareMatrix lu[]=new AbstractDoubleSquareMatrix[2]; 520 lu[0]=new DoubleSquareMatrix(arrayL); 521 lu[1]=new DoubleSquareMatrix(arrayU); 522 return lu; 523 } 524 525 527 533 public AbstractDoubleSquareMatrix[] qrDecompose() { 534 final int N=numRows; 535 final double array[][]=new double[N][N]; 536 final double arrayQ[][]=new double[N][N]; 537 final double arrayR[][]=new double[N][N]; 538 for(int i=0;i<N;i++) { 540 array[i][0]=getElement(i,0); 541 for(int j=1;j<N;j++) 542 array[i][j]=getElement(i,j); 543 } 544 for(int k=0; k<N; k++) { 545 double norm = array[k][k]; 547 for(int i=k+1; i<N; i++) 548 norm = ExtraMath.hypot(norm, array[i][k]); 549 if(norm != 0.0) { 550 if(array[k][k] < 0.0) 552 norm = -norm; 553 for(int i=k; i<N; i++) 554 array[i][k] /= norm; 555 array[k][k] += 1.0; 556 for(int j=k+1; j<N; j++) { 558 double s=array[k][k]*array[k][j]; 559 for(int i=k+1; i<N; i++) 560 s += array[i][k]*array[i][j]; 561 s /= array[k][k]; 562 for(int i=k; i<N; i++) 563 array[i][j] -= s*array[i][k]; 564 } 565 } 566 arrayR[k][k] = -norm; 567 } 568 for(int k=N-1; k>=0; k--) { 569 arrayQ[k][k] = 1.0; 570 for(int j=k; j<N; j++) { 571 if(array[k][k] != 0.0) { 572 double s = array[k][k]*arrayQ[k][j]; 573 for(int i=k+1; i<N; i++) 574 s += array[i][k]*arrayQ[i][j]; 575 s /= array[k][k]; 576 for(int i=k; i<N; i++) 577 arrayQ[i][j] -= s*array[i][k]; 578 } 579 } 580 } 581 for(int i=0; i<N; i++) { 582 for(int j=i+1; j<N; j++) 583 arrayR[i][j] = array[i][j]; 584 } 585 final AbstractDoubleSquareMatrix qr[]=new AbstractDoubleSquareMatrix[2]; 586 qr[0]=new DoubleSquareMatrix(arrayQ); 587 qr[1]=new DoubleSquareMatrix(arrayR); 588 return qr; 589 } 590 591 593 599 public AbstractDoubleSquareMatrix[] singularValueDecompose() { 600 final int N=numRows; 601 final int Nm1=N-1; 602 final double array[][]=new double[N][N]; 603 final double arrayU[][]=new double[N][N]; 604 final double arrayS[]=new double[N]; 605 final double arrayV[][]=new double[N][N]; 606 final double e[]=new double[N]; 607 final double work[]=new double[N]; 608 for(int i=0;i<N;i++) { 610 array[i][0]=getElement(i,0); 611 for(int j=1;j<N;j++) 612 array[i][j]=getElement(i,j); 613 } 614 for(int k=0;k<Nm1;k++) { 616 arrayS[k]=array[k][k]; 619 for(int i=k+1;i<N;i++) 620 arrayS[k]=ExtraMath.hypot(arrayS[k],array[i][k]); 621 if(arrayS[k]!=0.0) { 622 if(array[k][k]<0.0) 623 arrayS[k]=-arrayS[k]; 624 for(int i=k;i<N;i++) 625 array[i][k]/=arrayS[k]; 626 array[k][k]+=1.0; 627 } 628 arrayS[k]=-arrayS[k]; 629 for(int j=k+1;j<N;j++) { 630 if(arrayS[k]!=0.0) { 631 double t=array[k][k]*array[k][j]; 633 for(int i=k+1; i<N; i++) 634 t+=array[i][k]*array[i][j]; 635 t /= array[k][k]; 636 for(int i=k; i<N; i++) 637 array[i][j] -= t*array[i][k]; 638 } 639 e[j]=array[k][j]; 640 } 641 for(int i=k;i<N;i++) 642 arrayU[i][k]=array[i][k]; 643 if(k<N-2) { 644 e[k]=e[k+1]; 647 for(int i=k+2;i<N;i++) 648 e[k]=ExtraMath.hypot(e[k],e[i]); 649 if(e[k]!=0.0) { 650 if(e[k+1]<0.0) 651 e[k]=-e[k]; 652 for(int i=k+1;i<N;i++) 653 e[i]/=e[k]; 654 e[k+1]+=1.0; 655 } 656 e[k]=-e[k]; 657 if(e[k]!=0.0) { 658 for(int i=k+1;i<N;i++) { 660 work[i]=0.0; 661 for(int j=k+1;j<N;j++) 662 work[i]+=e[j]*array[i][j]; 663 } 664 for(int j=k+1;j<N;j++) { 665 double t = e[j]/e[k+1]; 666 for(int i=k+1;i<N;i++) 667 array[i][j] -= t*work[i]; 668 } 669 } 670 for(int i=k+1;i<N;i++) 671 arrayV[i][k]=e[i]; 672 } 673 } 674 int p=N; 676 arrayS[Nm1]=array[Nm1][Nm1]; 677 e[N-2]=array[N-2][Nm1]; 678 e[Nm1]=0.0; 679 arrayU[Nm1][Nm1]=1.0; 680 for(int k=N-2;k>=0;k--) { 681 if(arrayS[k]!=0.0) { 682 for(int j=k+1;j<N;j++) { 683 double t=arrayU[k][k]*arrayU[k][j]; 684 for(int i=k+1;i<N;i++) 685 t+=arrayU[i][k]*arrayU[i][j]; 686 t /= arrayU[k][k]; 687 for(int i=k;i<N;i++) 688 arrayU[i][j] -= t*arrayU[i][k]; 689 } 690 for(int i=k;i<N;i++) 691 arrayU[i][k]=-arrayU[i][k]; 692 arrayU[k][k]+=1.0; 693 for(int i=0;i<k-1;i++) 694 arrayU[i][k]=0.0; 695 } else { 696 for(int i=0;i<N;i++) 697 arrayU[i][k]=0.0; 698 arrayU[k][k]=1.0; 699 } 700 } 701 for(int k=Nm1;k>=0;k--) { 702 if(k<N-2 && e[k]!=0.0) { 703 for(int j=k+1;j<N;j++) { 704 double t=arrayV[k+1][k]*arrayV[k+1][j]; 705 for(int i=k+2;i<N;i++) 706 t+=arrayV[i][k]*arrayV[i][j]; 707 t /= arrayV[k+1][k]; 708 for(int i=k+1;i<N;i++) 709 arrayV[i][j] -= t*arrayV[i][k]; 710 } 711 } 712 for(int i=0;i<N;i++) 713 arrayV[i][k]=0.0; 714 arrayV[k][k]=1.0; 715 } 716 final double eps=Math.pow(2.0,-52.0); 717 int iter=0; 718 while(p>0) { 719 int k,action; 720 for(k=p-2;k>=-1;k--) { 725 if(k==-1) 726 break; 727 if(Math.abs(e[k])<=eps*(Math.abs(arrayS[k])+Math.abs(arrayS[k+1]))) { 728 e[k]=0.0; 729 break; 730 } 731 } 732 if(k==p-2) { 733 action=4; 734 } else { 735 int ks; 736 for(ks=p-1;ks>=k;ks--) { 737 if(ks==k) 738 break; 739 double t=(ks!=p ? Math.abs(e[ks]) : 0.0)+(ks!=k+1 ? Math.abs(e[ks-1]) : 0.0); 740 if(Math.abs(arrayS[ks])<=eps*t) { 741 arrayS[ks]=0.0; 742 break; 743 } 744 } 745 if(ks==k) { 746 action=3; 747 } else if(ks==p-1) { 748 action=1; 749 } else { 750 action=2; 751 k=ks; 752 } 753 } 754 k++; 755 switch(action) { 756 case 1: { 758 double f=e[p-2]; 759 e[p-2]=0.0; 760 for(int j=p-2;j>=k;j--) { 761 double t=ExtraMath.hypot(arrayS[j],f); 762 final double cs=arrayS[j]/t; 763 final double sn=f/t; 764 arrayS[j]=t; 765 if(j!=k) { 766 f=-sn*e[j-1]; 767 e[j-1]*=cs; 768 } 769 for(int i=0;i<N;i++) { 770 t=cs*arrayV[i][j]+sn*arrayV[i][p-1]; 771 arrayV[i][p-1]=-sn*arrayV[i][j]+cs*arrayV[i][p-1]; 772 arrayV[i][j]=t; 773 } 774 } 775 } break; 776 case 2: { 778 double f=e[k-1]; 779 e[k-1]=0.0; 780 for(int j=k;j<p;j++) { 781 double t=ExtraMath.hypot(arrayS[j],f); 782 final double cs=arrayS[j]/t; 783 final double sn=f/t; 784 arrayS[j]=t; 785 f=-sn*e[j]; 786 e[j]*=cs; 787 for(int i=0;i<N;i++) { 788 t=cs*arrayU[i][j]+sn*arrayU[i][k-1]; 789 arrayU[i][k-1]=-sn*arrayU[i][j]+cs*arrayU[i][k-1]; 790 arrayU[i][j]=t; 791 } 792 } 793 } break; 794 case 3: { 796 final double scale=Math.max(Math.max(Math.max(Math.max( 798 Math.abs(arrayS[p-1]),Math.abs(arrayS[p-2])),Math.abs(e[p-2])), 799 Math.abs(arrayS[k])),Math.abs(e[k])); 800 double sp=arrayS[p-1]/scale; 801 double spm1=arrayS[p-2]/scale; 802 double epm1=e[p-2]/scale; 803 double sk=arrayS[k]/scale; 804 double ek=e[k]/scale; 805 double b=((spm1+sp)*(spm1-sp)+epm1*epm1)/2.0; 806 double c=(sp*epm1)*(sp*epm1); 807 double shift=0.0; 808 if(b!=0.0 || c!=0.0) { 809 shift=Math.sqrt(b*b+c); 810 if(b<0.0) 811 shift=-shift; 812 shift=c/(b+shift); 813 } 814 double f=(sk+sp)*(sk-sp)+shift; 815 double g=sk*ek; 816 for(int j=k;j<p-1;j++) { 818 double t=ExtraMath.hypot(f,g); 819 double cs=f/t; 820 double sn=g/t; 821 if(j!=k) 822 e[j-1]=t; 823 f=cs*arrayS[j]+sn*e[j]; 824 e[j]=cs*e[j]-sn*arrayS[j]; 825 g=sn*arrayS[j+1]; 826 arrayS[j+1]*=cs; 827 for(int i=0;i<N;i++) { 828 t=cs*arrayV[i][j]+sn*arrayV[i][j+1]; 829 arrayV[i][j+1]=-sn*arrayV[i][j]+cs*arrayV[i][j+1]; 830 arrayV[i][j]=t; 831 } 832 t=ExtraMath.hypot(f,g); 833 cs=f/t; 834 sn=g/t; 835 arrayS[j]=t; 836 f=cs*e[j]+sn*arrayS[j+1]; 837 arrayS[j+1]=-sn*e[j]+cs*arrayS[j+1]; 838 g=sn*e[j+1]; 839 e[j+1]*=cs; 840 if(j<Nm1) { 841 for(int i=0;i<N;i++) { 842 t=cs*arrayU[i][j]+sn*arrayU[i][j+1]; 843 arrayU[i][j+1]=-sn*arrayU[i][j]+cs*arrayU[i][j+1]; 844 arrayU[i][j]=t; 845 } 846 } 847 } 848 e[p-2]=f; 849 iter++; 850 } break; 851 case 4: { 853 if(arrayS[k]<=0.0) { 855 arrayS[k]=-arrayS[k]; 856 for(int i=0;i<p;i++) 857 arrayV[i][k]=-arrayV[i][k]; 858 } 859 while(k<p-1) { 861 if(arrayS[k]>=arrayS[k+1]) 862 break; 863 double tmp=arrayS[k]; 864 arrayS[k]=arrayS[k+1]; 865 arrayS[k+1]=tmp; 866 if(k<Nm1) { 867 for(int i=0;i<N;i++) { 868 tmp=arrayU[i][k+1]; 869 arrayU[i][k+1]=arrayU[i][k]; 870 arrayU[i][k]=tmp; 871 tmp=arrayV[i][k+1]; 872 arrayV[i][k+1]=arrayV[i][k]; 873 arrayV[i][k]=tmp; 874 } 875 } 876 k++; 877 } 878 iter=0; 879 p--; 880 } break; 881 } 882 } 883 final AbstractDoubleSquareMatrix svd[]=new AbstractDoubleSquareMatrix[3]; 884 svd[0]=new DoubleSquareMatrix(arrayU); 885 svd[1]=new DoubleDiagonalMatrix(arrayS); 886 svd[2]=new DoubleSquareMatrix(arrayV); 887 return svd; 888 } 889 890 892 895 public AbstractDoubleSquareMatrix[] polarDecompose() { 896 final int N=numRows; 897 final AbstractDoubleVector evec[]=new AbstractDoubleVector[N]; 898 double eval[]; 899 try { 900 eval=LinearMath.eigenSolveSymmetric(this,evec); 901 } catch(MaximumIterationsExceededException e) { 902 return null; 903 } 904 final double tmpa[][]=new double[N][N]; 905 final double tmpm[][]=new double[N][N]; 906 double abs; 907 for(int i=0;i<N;i++) { 908 abs=Math.abs(eval[i]); 909 tmpa[i][0]=eval[i]*evec[i].getComponent(0)/abs; 910 tmpm[i][0]=abs*evec[i].getComponent(0); 911 for(int j=1;j<N;j++) { 912 tmpa[i][j]=eval[i]*evec[i].getComponent(j)/abs; 913 tmpm[i][j]=abs*evec[i].getComponent(j); 914 } 915 } 916 final double arg[][]=new double[N][N]; 917 final double mod[][]=new double[N][N]; 918 for(int i=0;i<N;i++) { 919 for(int j=0;j<N;j++) { 920 arg[i][j]=evec[0].getComponent(i)*tmpa[0][j]; 921 mod[i][j]=evec[0].getComponent(i)*tmpm[0][j]; 922 for(int k=1;k<N;k++) { 923 arg[i][j]+=evec[k].getComponent(i)*tmpa[k][j]; 924 mod[i][j]+=evec[k].getComponent(i)*tmpm[k][j]; 925 } 926 } 927 } 928 final AbstractDoubleSquareMatrix us[]=new AbstractDoubleSquareMatrix[2]; 929 us[0]=new DoubleSquareMatrix(arg); 930 us[1]=new DoubleSquareMatrix(mod); 931 return us; 932 } 933 934 936 941 public AbstractDoubleMatrix mapElements(final Mapping f) { 942 final double array[][]=new double[numRows][numCols]; 943 for(int i=0;i<numRows;i++) { 944 array[i][0] = f.map(getElement(i,0)); 945 for(int j=1;j<numCols;j++) 946 array[i][j] = f.map(getElement(i,j)); 947 } 948 return new DoubleSquareMatrix(array); 949 } 950 951 private static class SquareMatrixAdaptor extends AbstractDoubleSquareMatrix { 952 private final AbstractDoubleMatrix matrix; 953 private SquareMatrixAdaptor(AbstractDoubleMatrix m) { 954 super(m.rows()); 955 matrix = m; 956 } 957 public double getElement(int i, int j) { 958 return matrix.getElement(i,j); 959 } 960 public void setElement(int i, int j, double x) { 961 matrix.setElement(i,j, x); 962 } 963 } 964 } 965 | Popular Tags |