/* Description: Find the eigen values and eigen vectors of a real symmetric 3x3 matrix A D F D B E F E C Parameters: A - [in] matrix entry B - [in] matrix entry C - [in] matrix entry D - [in] matrix entry E - [in] matrix entry F - [in] matrix entry e1 - [out] eigen value E1 - [out] eigen vector with eigen value e1 e2 - [out] eigen value E2 - [out] eigen vector with eigen value e2 e3 - [out] eigen value E3 - [out] eigen vector with eigen value e3 Returns: True if successful. */ bool ON_Sym3x3EigenSolver( double A, double B, double C, double D, double E, double F, double* e1, ON_3dVector E1, double* e2, ON_3dVector E2, double* e3, ON_3dVector E3 ) { // STEP 1: reduce to tri-diagonal form double cos_phi = 1.0; double sin_phi = 0.0; double AA = A, BB = B, CC = C, DD = D, EE = E, FF = F; if ( F != 0.0 ) { double theta = 0.5*(C-A)/F; double t; if ( fabs(theta) > 1.0e154 ) { t = 0.5/fabs(theta); } else if ( fabs(theta) > 1.0 ) { t = 1.0/(fabs(theta)*(1.0 + sqrt(1.0 + 1.0/(theta*theta)))); } else { t = 1.0/(fabs(theta) + sqrt(1.0+theta*theta)); } if ( theta < 0.0 ) t = -t; if ( fabs(t) > 1.0 ) { double tt = 1.0/t; cos_phi = 1.0/(fabs(t)*sqrt(1.0 + tt*tt)); } else cos_phi = 1.0/sqrt(1.0 + t*t); sin_phi = t*cos_phi; double tau = sin_phi/(1.0 + cos_phi); AA = A - t*F; BB = B; CC = C + t*F; DD = D - sin_phi*(E + tau*D); EE = E + sin_phi*(D + tau*E); // debugging test - FF should be close to zero. // cos_phi*cos_phi + sin_phi*size_phi should be close to 1 FF = (cos_phi*cos_phi - sin_phi*sin_phi)*F + sin_phi*cos_phi*(A-C); } double ee1, ee2, ee3; ON_3dVector EE1, EE2, EE3; bool rc = ON_SymTriDiag3x3EigenSolver( AA, BB, CC, DD, EE, &ee1, EE1, &ee2, EE2, &ee3, EE3 ); E1.Set(cos_phi*EE1.x - sin_phi*EE1.z, EE1.y, sin_phi*EE1.x + cos_phi*EE1.z ); E2.Set(cos_phi*EE2.x - sin_phi*EE2.z, EE2.y, sin_phi*EE2.x + cos_phi*EE2.z ); E3.Set(cos_phi*EE3.x - sin_phi*EE3.z, EE3.y, sin_phi*EE3.x + cos_phi*EE3.z ); if ( e1 ) *e1 = ee1; if ( e2 ) *e2 = ee2; if ( e3 ) *e3 = ee3; // debugging check of eigen values ON_3dVector err1, err2, err3; { err1.x = (A*E1.x + D*E1.y + F*E1.z) - ee1*E1.x; err1.y = (D*E1.x + B*E1.y + E*E1.z) - ee1*E1.y; err1.z = (F*E1.x + E*E1.y + C*E1.z) - ee1*E1.z; err2.x = (A*E2.x + D*E2.y + F*E2.z) - ee2*E2.x; err2.y = (D*E2.x + B*E2.y + E*E2.z) - ee2*E2.y; err2.z = (F*E2.x + E*E2.y + C*E2.z) - ee2*E2.z; err3.x = (A*E3.x + D*E3.y + F*E3.z) - ee3*E3.x; err3.y = (D*E3.x + B*E3.y + E*E3.z) - ee3*E3.y; err3.z = (F*E3.x + E*E3.y + C*E3.z) - ee3*E3.z; } return rc; }