// This method computes all principal angles using a sine based algorithm. // Small angles are computed more accurately than larger angles public static double[] getPrincipleAngles(DenseMatrix X, DenseMatrix Y) { double[] s = new double[0]; if (X.numColumns() == 0 || Y.numColumns() == 0) return s; DenseMatrix QX; DenseMatrix QY; // Orthonormalize X and Y if (X.numColumns() < Y.numColumns()) { // Switch X and Y in this case QX = Utilities.orth(Y); QY = Utilities.orth(X); } else { QX = Utilities.orth(X); QY = Utilities.orth(Y); } // Compute QY=QY-QX*(QX^T*QY) DenseMatrix Z = new DenseMatrix(QX.numRows(), QY.numColumns()); DenseMatrix Temp1 = new DenseMatrix(QX.numColumns(), QX.numRows()); DenseMatrix Temp2 = new DenseMatrix(QX.numColumns(), QY.numColumns()); QX.transpose(Temp1); // Temp1=QX^T Temp1.mult(QY, Temp2); // Temp2=Temp1*QY=QX^T*QY QX.mult(Temp2, Z); QY.add(-1D, Z); // Now compute the singular values try { SVD svd = SVD.factorize(QY); s = svd.getS(); } catch (NotConvergedException e) { } // Return angles in radians for (int i = 0; i < s.length; ++i) s[i] = Math.asin(s[i]); return s; }