/* Polar Decomposition of 3x3 matrix in 4x4, * M = QS. See Nicholas Higham and Robert S. Schreiber, * Fast Polar Decomposition of An Arbitrary Matrix, * Technical Report 88-942, October 1988, * Department of Computer Science, Cornell University. */ double polar_decomp(HMatrix M, HMatrix Q, HMatrix S) { #define TOL 1.0e-6 HMatrix Mk, MadjTk, Ek; double det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2; int i, j; mat_tpose(Mk,=,M,3); M_one = norm_one(Mk); M_inf = norm_inf(Mk); do { adjoint_transpose(Mk, MadjTk); det = vdot(Mk[0], MadjTk[0]); if (det==0.0) {do_rank2(Mk, MadjTk, Mk); break;} MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk); gamma = sqrt(sqrt((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(det)); g1 = gamma*0.5; g2 = 0.5/(gamma*det); mat_copy(Ek,=,Mk,3); mat_binop(Mk,=,g1*Mk,+,g2*MadjTk,3); mat_copy(Ek,-=,Mk,3); E_one = norm_one(Ek); M_one = norm_one(Mk); M_inf = norm_inf(Mk); } while (E_one>(M_one*TOL)); mat_tpose(Q,=,Mk,3); mat_pad(Q); mat_mult(Mk, M, S); mat_pad(S); for (i=0; i<3; i++) for (j=i; j<3; j++) S[i][j] = S[j][i] = 0.5*(S[i][j]+S[j][i]); return (det); }
/* Polar Decomposition of 3x3 matrix in 4x4, * M = QS. See Nicholas Higham and Robert S. Schreiber, * Fast Polar Decomposition of An Arbitrary Matrix, * Technical Report 88-942, October 1988, * Department of Computer Science, Cornell University. */ float polar_decomp(const mat3 & M, mat3 & Q, mat3 & S) { mat3 tmp; mat3 Mk, MadjTk, Ek; nv_scalar d, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2; transpose(Mk,M); M_one = Mk.norm_one(); M_inf = Mk.norm_inf(); do { invert(MadjTk,Mk); transpose(MadjTk); MadjTk*=det(MadjTk); d = dot(Mk.col(0), MadjTk.col(0)); if (d == nv_zero) { do_rank2(Mk, MadjTk, Mk); break; } MadjT_one = MadjTk.norm_one(); MadjT_inf = MadjTk.norm_inf(); gamma = sqrtf(sqrtf((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(d)); g1 = gamma*nv_zero_5; g2 = nv_zero_5 / (gamma*d); Ek = Mk; tmp = Mk; tmp *= g1; MadjTk *= g2; add(Mk,tmp,MadjTk); Ek-=Mk; E_one = Ek.norm_one(); M_one = Mk.norm_one(); M_inf = Mk.norm_inf(); } while (E_one>(M_one*nv_eps)); transpose(Q,Mk); mult(S, Mk, M); nv_scalar x; for (int i = 0; i < 3; ++i) { for (int j = i; j < 3; ++j) { x = nv_zero_5 * (S[i][j]+S[j][i]); S(i,j) = x; S(j,i) = x; } } return (d); }