#include <math.h>
Go to the source code of this file.
Functions | |
void | svd22 (const double A[4], double U[4], double S[2], double V[4]) |
void | svd_sym_singular_values (double A00, double A01, double A11, double *Lmin, double *Lmax) |
void svd22 | ( | const double | A[4], |
double | U[4], | ||
double | S[2], | ||
double | V[4] | ||
) |
SVD 2x2.
Computes singular values and vectors without squaring the input matrix. With double precision math, results are accurate to about 1E-16.
U = [ cos(theta) -sin(theta) ] [ sin(theta) cos(theta) ]
S = [ e 0 ] [ 0 f ]
V = [ cos(phi) -sin(phi) ] [ sin(phi) cos(phi) ]
Our strategy is basically to analytically multiply everything out and then rearrange so that we can solve for theta, phi, e, and f. (Derivation by ebolson@umich.edu 5/2016)
V' = [ CP SP ] [ -SP CP ]
USV' = [ CT -ST ][ e*CP e*SP ] [ ST CT ][ -f*SP f*CP ]
= [e*CT*CP + f*ST*SP e*CT*SP - f*ST*CP ] [e*ST*CP - f*SP*CT e*SP*ST + f*CP*CT ]
A00+A11 = e*CT*CP + f*ST*SP + e*SP*ST + f*CP*CT = e*(CP*CT + SP*ST) + f*(SP*ST + CP*CT) = (e+f)(CP*CT + SP*ST) B0 = (e+f)*cos(P-T)
A00-A11 = e*CT*CP + f*ST*SP - e*SP*ST - f*CP*CT = e*(CP*CT - SP*ST) - f*(-ST*SP + CP*CT) = (e-f)(CP*CT - SP*ST) B1 = (e-f)*cos(P+T)
A01+A10 = e*CT*SP - f*ST*CP + e*ST*CP - f*SP*CT = e(CT*SP + ST*CP) - f*(ST*CP + SP*CT) = (e-f)*(CT*SP + ST*CP) B2 = (e-f)*sin(P+T)
A01-A10 = e*CT*SP - f*ST*CP - e*ST*CP + f*SP*CT = e*(CT*SP - ST*CP) + f(SP*CT - ST*CP) = (e+f)*(CT*SP - ST*CP) B3 = (e+f)*sin(P-T)
B0 = (e+f)*cos(P-T) B1 = (e-f)*cos(P+T) B2 = (e-f)*sin(P+T) B3 = (e+f)*sin(P-T)
B3/B0 = tan(P-T)
B2/B1 = tan(P+T)