package util.linalg; /** * A class representing a givens rotations, which is a matrix * of the form G = [ ... ; cosine, ..., sine; ... ; -sine, ..., cosine; ... ], * a rotation of a certain angle that affects two rows of a matrix * when applied to a matrix from the left A = Gt * A, and affects * two columns of a matrix when applied to a matrix from the right * A = A * G * @author Andrew Guillory gtg008g@mail.gatech.edu * @version 1.0 */ public class GivensRotation { /** * The cosine of the angle */ private double cosine; /** * The sine of the angle */ private double sine; /** * Create a new givens rotation * @param theta the angle of the rotation */ public GivensRotation(double theta) { cosine = Math.cos(theta); sine = Math.sin(theta); } /** * Create a new givens rotation which when applied * from the left to a column vector V = [..., a, ..., b]t * where a and b are the ith and jth entries in the vector * produces a column vector [..., r, ..., 0]t = Gt * V that has zero * in the jth position and some value r in the ith position. * @param a the entry in the ith dimension * @parma b the entry in the jth dimension */ public GivensRotation(double a, double b) { if (b == 0) { cosine = 1; sine = 0; } else { if (Math.abs(b) > Math.abs(a)) { double t = -a / b; sine = 1 / Math.sqrt(1 + t * t); cosine = sine * t; } else { double t = -b / a; cosine = 1 / Math.sqrt(1 + t * t); sine = cosine * t; } } } /** * Apply this rotation from the left to the given matrix. * Sets M = Gt * M. * @param m the matrix to apply the rotation to * @param i the first row to affect in the rotation * @param j the second row j > i to affect in the rotation */ public void applyLeft(Matrix m, int i, int j) { // loop through all of the columns, only // affecting rows i and j for (int k = 0; k < m.n(); k++) { double vi = m.get(i, k); double vj = m.get(j, k); m.set(i,k, cosine * vi - sine*vj); m.set(j,k, sine * vi + cosine*vj); } } /** * Apply this rotation from the right to the given matrix. * Sets M = M * G. * @param m the matrix to apply the rotation to * @param i the first column to affect in the rotation * @param j the second column j > i to affect in the rotation */ public void applyRight(Matrix m, int i, int j) { // loop through all of the rows, only // affecting columns i and j for (int k = 0; k < m.m(); k++) { double vi = m.get(k, i); double vj = m.get(k, j); m.set(k,i, cosine * vi - sine*vj); m.set(k,j, sine * vi + cosine*vj); } } }