Matrix3SVD.cc

Go to the documentation of this file.
00001 
00002 #include <iostream>
00003 #include <vecmath/Matrix3SVD.h>
00004 
00005 const double Matrix3SVD::EPS1 = 1.110223024E-16;
00006 const double Matrix3SVD::EPS2 = 4.89E-15;
00007 const double Matrix3SVD::EPS3 = 1E-08;
00008 
00009 // should be reworked later
00010 // for now it just works
00011 
00012 bool Matrix3SVD::almostEqual(double d, double d1)
00013 {
00014     if (d == d1)
00015         return true;
00016     const double d2 = 1E-06;
00017     //double d3 = 0.0001;
00018     double d4 = Math::abs(d - d1);
00019     double d5 = Math::abs(d);
00020     double d6 = Math::abs(d1);
00021     double d7 = d5 < d6 ? d6 : d5;
00022     if (d4 < d2)
00023         return true;
00024     return d4 / d7 < 0.0001;
00025 }
00026 
00027 int Matrix3SVD::compute_2X2(double d, double d1, double d2, double ad[], double ad1[],
00028                             double ad2[], double ad3[], double ad4[], int i)
00029 {
00030     double d3 = 2.0;
00031     double d4 = 1.0;
00032     double d37 = ad[0];
00033     double d36 = ad[1];
00034     double d32 = 0.0;
00035     double d33 = 0.0;
00036     double d34 = 0.0;
00037     double d35 = 0.0;
00038     double d21 = 0.0;
00039     double d25 = d;
00040     double d22 = Math::abs(d25);
00041     double d27 = d2;
00042     double d24 = Math::abs(d2);
00043     unsigned char byte0 = 1;
00044     bool flag;
00045     if (d24 > d22)
00046         flag = true;
00047     else
00048         flag = false;
00049     if (flag) {
00050         byte0 = 3;
00051         double d6 = d25;
00052         d25 = d27;
00053         d27 = d6;
00054         d6 = d22;
00055         d22 = d24;
00056         d24 = d6;
00057     }
00058     double d26 = d1;
00059     double d23 = Math::abs(d26);
00060     if (d23 == 0.0) {
00061         ad[1] = d24;
00062         ad[0] = d22;
00063         d32 = 1.0;
00064         d33 = 1.0;
00065         d34 = 0.0;
00066         d35 = 0.0;
00067     } else {
00068         bool flag1 = true;
00069         if (d23 > d22) {
00070             byte0 = 2;
00071             if (d22 / d23 < EPS1) {
00072                 flag1 = false;
00073                 d37 = d23;
00074                 if (d24 > 1.0)
00075                     d36 = d22 / (d23 / d24);
00076                 else
00077                     d36 = (d22 / d23) * d24;
00078                 d32 = 1.0;
00079                 d34 = d27 / d26;
00080                 d35 = 1.0;
00081                 d33 = d25 / d26;
00082             }
00083         }
00084         if (flag1) {
00085             double d9 = d22 - d24;
00086             double d11;
00087             if (d9 == d22)
00088                 d11 = 1.0;
00089             else
00090                 d11 = d9 / d22;
00091             double d13 = d26 / d25;
00092             //double d19 = 2.0 - d11;
00093             double d28 = d13 * d13;
00094             //double d30 = d19 * d19;
00095             //double d17 = sqrt(d30 + d28);
00096             double d15;
00097             if (d11 == 0.0)
00098                 d15 = Math::abs(d13);
00099             else
00100                 d15 = sqrt(d11 * d11 + d28);
00101             //double d7 = (d17 + d15) * 0.5;
00102             if (d23 > d22) {
00103                 byte0 = 2;
00104                 if (d22 / d23 < EPS1) {
00105                     flag1 = false;
00106                     d37 = d23;
00107                     if (d24 > 1.0)
00108                         d36 = d22 / (d23 / d24);
00109                     else
00110                         d36 = (d22 / d23) * d24;
00111                     d32 = 1.0;
00112                     d34 = d27 / d26;
00113                     d35 = 1.0;
00114                     d33 = d25 / d26;
00115                 }
00116             }
00117             if (flag1) {
00118                 double d10 = d22 - d24;
00119                 double d12;
00120                 if (d10 == d22)
00121                     d12 = 1.0;
00122                 else
00123                     d12 = d10 / d22;
00124                 double d14 = d26 / d25;
00125                 double d20 = 2.0 - d12;
00126                 double d29 = d14 * d14;
00127                 double d31 = d20 * d20;
00128                 double d18 = sqrt(d31 + d29);
00129                 double d16;
00130                 if (d12 == 0.0)
00131                     d16 = Math::abs(d14);
00132                 else
00133                     d16 = sqrt(d12 * d12 + d29);
00134                 double d8 = (d18 + d16) * 0.5;
00135                 d36 = d24 / d8;
00136                 d37 = d22 * d8;
00137                 if (d29 == 0.0) {
00138                     if (d12 == 0.0)
00139                         d20 = d_sign(d3, d25) * d_sign(d4, d26);
00140                     else
00141                         d20 = d26 / d_sign(d10, d25) + d14 / d20;
00142                 } else {
00143                     d20 = (d14 / (d18 + d20) + d14 / (d16 + d12)) * (d8 + 1.0);
00144                 }
00145                 d12 = sqrt(d20 * d20 + 4);
00146                 d33 = 2.0 / d12;
00147                 d35 = d20 / d12;
00148                 d32 = (d33 + d35 * d14) / d8;
00149                 d34 = ((d27 / d25) * d35) / d8;
00150             }
00151         }
00152         if (flag) {
00153             ad2[0] = d35;
00154             ad1[0] = d33;
00155             ad4[0] = d34;
00156             ad3[0] = d32;
00157         } else {
00158             ad2[0] = d32;
00159             ad1[0] = d34;
00160             ad4[0] = d33;
00161             ad3[0] = d35;
00162         }
00163         if (byte0 == 1)
00164             d21 = d_sign(d4, ad4[0]) * d_sign(d4, ad2[0]) * d_sign(d4, d);
00165         if (byte0 == 2)
00166             d21 = d_sign(d4, ad3[0]) * d_sign(d4, ad2[0]) * d_sign(d4, d1);
00167         if (byte0 == 3)
00168             d21 = d_sign(d4, ad3[0]) * d_sign(d4, ad1[0]) * d_sign(d4, d2);
00169         ad[i] = d_sign(d37, d21);
00170         double d5 = d21 * d_sign(d4, d) * d_sign(d4, d2);
00171         ad[i + 1] = d_sign(d36, d5);
00172     }
00173     return 0;
00174 }
00175 
00176 int Matrix3SVD::compute_qr(double ad[], double ad1[], double ad2[], double ad3[], bool flag)
00177 {
00178     double ad4[2];
00179     double ad5[2];
00180     double ad6[2];
00181     double ad7[2];
00182     double ad8[9];
00183     double ad9[9];
00184     double ad10[9];
00185     double ad11[9];
00186     //unsigned char byte0 = 10;
00187     double d11 = 1.0;
00188     bool flag1 = false;
00189     if (flag) {
00190             std::cout << " \nu  = \n" << std::endl;
00191         print_mat(ad2);
00192         std::cout << " \nv  = \n" << std::endl;
00193         print_mat(ad3);
00194         ad8[0] = ad[0];
00195         ad8[1] = ad1[0];
00196         ad8[2] = 0.0;
00197         ad8[3] = 0.0;
00198         ad8[4] = ad[1];
00199         ad8[5] = ad1[1];
00200         ad8[6] = 0.0;
00201         ad8[7] = 0.0;
00202         ad8[8] = ad[2];
00203         transpose_mat(ad2, ad9);
00204         mat_mul(ad9, ad8, ad11);
00205         transpose_mat(ad3, ad10);
00206         mat_mul(ad11, ad10, ad11);
00207         std::cout << "\nA=\n" << std::endl;
00208         print_mat(ad11);
00209     }
00210     int j = 1;
00211     if (Math::abs(ad1[1]) < EPS2 || Math::abs(ad1[0]) < EPS2)
00212         flag1 = true;
00213     for (int i = 0; i < 10 && !flag1; i++) {
00214         double d = compute_shift(ad[1], ad1[1], ad[2]);
00215         double d8 = (Math::abs(ad[0]) - d) * (d_sign(d11, ad[0]) + d / ad[0]);
00216         double d9 = ad1[0];
00217         double d1 = compute_rot(d8, d9, ad7, ad5, 0, j);
00218         d8 = ad5[0] * ad[0] + ad7[0] * ad1[0];
00219         ad1[0] = ad5[0] * ad1[0] - ad7[0] * ad[0];
00220         d9 = ad7[0] * ad[1];
00221         ad[1] = ad5[0] * ad[1];
00222         d1 = compute_rot(d8, d9, ad6, ad4, 0, j);
00223         j = 0;
00224         ad[0] = d1;
00225         d8 = ad4[0] * ad1[0] + ad6[0] * ad[1];
00226         ad[1] = ad4[0] * ad[1] - ad6[0] * ad1[0];
00227         d9 = ad6[0] * ad1[1];
00228         ad1[1] = ad4[0] * ad1[1];
00229         d1 = compute_rot(d8, d9, ad7, ad5, 1, j);
00230         ad1[0] = d1;
00231         d8 = ad5[1] * ad[1] + ad7[1] * ad1[1];
00232         ad1[1] = ad5[1] * ad1[1] - ad7[1] * ad[1];
00233         d9 = ad7[1] * ad[2];
00234         ad[2] = ad5[1] * ad[2];
00235         d1 = compute_rot(d8, d9, ad6, ad4, 1, j);
00236         ad[1] = d1;
00237         d8 = ad4[1] * ad1[1] + ad6[1] * ad[2];
00238         ad[2] = ad4[1] * ad[2] - ad6[1] * ad1[1];
00239         ad1[1] = d8;
00240 
00241         double d2 = ad2[0];
00242         ad2[0] = ad4[0] * d2 + ad6[0] * ad2[3];
00243         ad2[3] = -ad6[0] * d2 + ad4[0] * ad2[3];
00244         d2 = ad2[1];
00245         ad2[1] = ad4[0] * d2 + ad6[0] * ad2[4];
00246         ad2[4] = -ad6[0] * d2 + ad4[0] * ad2[4];
00247         d2 = ad2[2];
00248         ad2[2] = ad4[0] * d2 + ad6[0] * ad2[5];
00249         ad2[5] = -ad6[0] * d2 + ad4[0] * ad2[5];
00250         d2 = ad2[3];
00251         ad2[3] = ad4[1] * d2 + ad6[1] * ad2[6];
00252         ad2[6] = -ad6[1] * d2 + ad4[1] * ad2[6];
00253         d2 = ad2[4];
00254         ad2[4] = ad4[1] * d2 + ad6[1] * ad2[7];
00255         ad2[7] = -ad6[1] * d2 + ad4[1] * ad2[7];
00256         d2 = ad2[5];
00257         ad2[5] = ad4[1] * d2 + ad6[1] * ad2[8];
00258         ad2[8] = -ad6[1] * d2 + ad4[1] * ad2[8];
00259 
00260         double d5 = ad3[0];
00261         ad3[0] = ad5[0] * d5 + ad7[0] * ad3[1];
00262         ad3[1] = -ad7[0] * d5 + ad5[0] * ad3[1];
00263         d5 = ad3[3];
00264         ad3[3] = ad5[0] * d5 + ad7[0] * ad3[4];
00265         ad3[4] = -ad7[0] * d5 + ad5[0] * ad3[4];
00266         d5 = ad3[6];
00267         ad3[6] = ad5[0] * d5 + ad7[0] * ad3[7];
00268         ad3[7] = -ad7[0] * d5 + ad5[0] * ad3[7];
00269         d5 = ad3[1];
00270         ad3[1] = ad5[1] * d5 + ad7[1] * ad3[2];
00271         ad3[2] = -ad7[1] * d5 + ad5[1] * ad3[2];
00272         d5 = ad3[4];
00273         ad3[4] = ad5[1] * d5 + ad7[1] * ad3[5];
00274         ad3[5] = -ad7[1] * d5 + ad5[1] * ad3[5];
00275         d5 = ad3[7];
00276         ad3[7] = ad5[1] * d5 + ad7[1] * ad3[8];
00277         ad3[8] = -ad7[1] * d5 + ad5[1] * ad3[8];
00278         if (flag)
00279             std::cout << "\n*********************** iteration #" << i << " ***********************\n" << std::endl;
00280         ad8[0] = ad[0];
00281         ad8[1] = ad1[0];
00282         ad8[2] = 0.0;
00283         ad8[3] = 0.0;
00284         ad8[4] = ad[1];
00285         ad8[5] = ad1[1];
00286         ad8[6] = 0.0;
00287         ad8[7] = 0.0;
00288         ad8[8] = ad[2];
00289         if (Math::abs(ad1[1]) < EPS2 || Math::abs(ad1[0]) < EPS2)
00290             flag1 = true;
00291     }
00292 
00293     if (Math::abs(ad1[1]) < EPS2) {
00294         compute_2X2(ad[0], ad1[0], ad[1], ad, ad6, ad4, ad7, ad5, 0);
00295         double d3 = ad2[0];
00296         ad2[0] = ad4[0] * d3 + ad6[0] * ad2[3];
00297         ad2[3] = -ad6[0] * d3 + ad4[0] * ad2[3];
00298         d3 = ad2[1];
00299         ad2[1] = ad4[0] * d3 + ad6[0] * ad2[4];
00300         ad2[4] = -ad6[0] * d3 + ad4[0] * ad2[4];
00301         d3 = ad2[2];
00302         ad2[2] = ad4[0] * d3 + ad6[0] * ad2[5];
00303         ad2[5] = -ad6[0] * d3 + ad4[0] * ad2[5];
00304         double d6 = ad3[0];
00305         ad3[0] = ad5[0] * d6 + ad7[0] * ad3[1];
00306         ad3[1] = -ad7[0] * d6 + ad5[0] * ad3[1];
00307         d6 = ad3[3];
00308         ad3[3] = ad5[0] * d6 + ad7[0] * ad3[4];
00309         ad3[4] = -ad7[0] * d6 + ad5[0] * ad3[4];
00310         d6 = ad3[6];
00311         ad3[6] = ad5[0] * d6 + ad7[0] * ad3[7];
00312         ad3[7] = -ad7[0] * d6 + ad5[0] * ad3[7];
00313     } else {
00314         compute_2X2(ad[1], ad1[1], ad[2], ad, ad6, ad4, ad7, ad5, 1);
00315         double d4 = ad2[3];
00316         ad2[3] = ad4[0] * d4 + ad6[0] * ad2[6];
00317         ad2[6] = -ad6[0] * d4 + ad4[0] * ad2[6];
00318         d4 = ad2[4];
00319         ad2[4] = ad4[0] * d4 + ad6[0] * ad2[7];
00320         ad2[7] = -ad6[0] * d4 + ad4[0] * ad2[7];
00321         d4 = ad2[5];
00322         ad2[5] = ad4[0] * d4 + ad6[0] * ad2[8];
00323         ad2[8] = -ad6[0] * d4 + ad4[0] * ad2[8];
00324         double d7 = ad3[1];
00325         ad3[1] = ad5[0] * d7 + ad7[0] * ad3[2];
00326         ad3[2] = -ad7[0] * d7 + ad5[0] * ad3[2];
00327         d7 = ad3[4];
00328         ad3[4] = ad5[0] * d7 + ad7[0] * ad3[5];
00329         ad3[5] = -ad7[0] * d7 + ad5[0] * ad3[5];
00330         d7 = ad3[7];
00331         ad3[7] = ad5[0] * d7 + ad7[0] * ad3[8];
00332         ad3[8] = -ad7[0] * d7 + ad5[0] * ad3[8];
00333     }
00334     return 0;
00335 }
00336 
00337 double Matrix3SVD::compute_rot(double d, double d1, double ad[], double ad1[], int i, int j)
00338 {
00339     const double d8 = 2.0020830951831009E-146;
00340     const double d9 = 4.9947976805055876E+145;
00341     double d2;
00342     double d3;
00343     double d7;
00344     if (d1 == 0.0) {
00345         d2 = 1.0;
00346         d3 = 0.0;
00347         d7 = d;
00348     } else
00349         if (d == 0.0) {
00350             d2 = 0.0;
00351             d3 = 1.0;
00352             d7 = d1;
00353         } else {
00354             double d5 = d;
00355             double d6 = d1;
00356             double d4 = max(Math::abs(d5), Math::abs(d6));
00357             if (d4 >= d9) {
00358                 int k1 = 0;
00359                 for (; d4 >= d9; d4 = max(Math::abs(d5), Math::abs(d6))) {
00360                     k1++;
00361                     d5 *= d8;
00362                     d6 *= d8;
00363                 }
00364 
00365                 d7 = sqrt(d5 * d5 + d6 * d6);
00366                 d2 = d5 / d7;
00367                 d3 = d6 / d7;
00368                 for (int i1 = 1; i1 <= k1; i1++)
00369                     d7 *= d9;
00370 
00371             } else
00372                 if (d4 <= d8) {
00373                     int l1 = 0;
00374                     for (; d4 <= d8; d4 = max(Math::abs(d5), Math::abs(d6))) {
00375                         l1++;
00376                         d5 *= d9;
00377                         d6 *= d9;
00378                     }
00379 
00380                     d7 = sqrt(d5 * d5 + d6 * d6);
00381                     d2 = d5 / d7;
00382                     d3 = d6 / d7;
00383                     for (int j1 = 1; j1 <= l1; j1++)
00384                         d7 *= d8;
00385 
00386                 } else {
00387                     d7 = sqrt(d5 * d5 + d6 * d6);
00388                     d2 = d5 / d7;
00389                     d3 = d6 / d7;
00390                 }
00391             if (Math::abs(d) > Math::abs(d1) && d2 < 0.0) {
00392                 d2 = -d2;
00393                 d3 = -d3;
00394                 d7 = -d7;
00395             }
00396         }
00397     ad[i] = d3;
00398     ad1[i] = d2;
00399     return d7;
00400 }
00401 
00402 double Matrix3SVD::compute_shift(double d, double d1, double d2)
00403 {
00404     double d11 = Math::abs(d);
00405     double d12 = Math::abs(d1);
00406     double d13 = Math::abs(d2);
00407     double d7 = min(d11, d13);
00408     double d8 = max(d11, d13);
00409     double d20;
00410     if (d7 == 0.0) {
00411         d20 = 0.0;
00412         double d3;
00413         if (d8 != 0.0)
00414             d3 = min(d8, d12) / max(d8, d12);
00415     } else
00416         if (d12 < d8) {
00417             double d14 = d7 / d8 + 1.0;
00418             double d16 = (d8 - d7) / d8;
00419             double d4 = d12 / d8;
00420             double d18 = d4 * d4;
00421             double d9 = 2.0 / (sqrt(d14 * d14 + d18) + sqrt(d16 * d16 + d18));
00422             d20 = d7 * d9;
00423         } else {
00424             double d19 = d8 / d12;
00425             if (d19 == 0.0) {
00426                 d20 = (d7 * d8) / d12;
00427             } else {
00428                 double d15 = d7 / d8 + 1.0;
00429                 double d17 = (d8 - d7) / d8;
00430                 double d5 = d15 * d19;
00431                 double d6 = d17 * d19;
00432                 double d10 = 1.0 / (sqrt(d5 * d5 + 1.0) + sqrt(d6 * d6 + 1.0));
00433                 d20 = d7 * d10 * d19;
00434                 d20 += d20;
00435             }
00436         }
00437     return d20;
00438 }
00439 
00440 void Matrix3SVD::compute_svd(double ad[], double scale[], double rot[], bool flag)
00441 {
00442     double ad3[9];
00443     double ad4[9];
00444     double ad5[9];
00445     double ad6[9];
00446     double ad7[9];
00447     double ad8[9];
00448     double ad9[9];
00449     double ad10[3];
00450     double ad11[3];
00451     double ad12[3];
00452     int l = 0;
00453     if (flag) {
00454             std::cout << "input to compute_svd = \n" << std::endl;
00455         print_mat(ad);
00456     }
00457 
00458     set(0.0, ad6);
00459 
00460     copy(ad, ad9); // ad -> ad9
00461 
00462     if (ad[3] * ad[3] < EPS1) {
00463         set(1.0, ad3);
00464     } else
00465         if (ad[0] * ad[0] < EPS1) {
00466             ad8[0] = ad[0];
00467             ad8[1] = ad[1];
00468             ad8[2] = ad[2];
00469             ad[0] = ad[3];
00470             ad[1] = ad[4];
00471             ad[2] = ad[5];
00472             ad[3] = -ad8[0];
00473             ad[4] = -ad8[1];
00474             ad[5] = -ad8[2];
00475             ad3[0] = 0.0;
00476             ad3[1] = 1.0;
00477             ad3[2] = 0.0;
00478             ad3[3] = -1;
00479             ad3[4] = 0.0;
00480             ad3[5] = 0.0;
00481             ad3[6] = 0.0;
00482             ad3[7] = 0.0;
00483             ad3[8] = 1.0;
00484         } else {
00485             double d = 1.0 / sqrt(ad[0] * ad[0] + ad[3] * ad[3]);
00486             double d4 = ad[0] * d;
00487             double d8 = ad[3] * d;
00488             ad8[0] = d4 * ad[0] + d8 * ad[3];
00489             ad8[1] = d4 * ad[1] + d8 * ad[4];
00490             ad8[2] = d4 * ad[2] + d8 * ad[5];
00491             ad[3] = -d8 * ad[0] + d4 * ad[3];
00492             ad[4] = -d8 * ad[1] + d4 * ad[4];
00493             ad[5] = -d8 * ad[2] + d4 * ad[5];
00494             ad[0] = ad8[0];
00495             ad[1] = ad8[1];
00496             ad[2] = ad8[2];
00497             ad3[0] = d4;
00498             ad3[1] = d8;
00499             ad3[2] = 0.0;
00500             ad3[3] = -d8;
00501             ad3[4] = d4;
00502             ad3[5] = 0.0;
00503             ad3[6] = 0.0;
00504             ad3[7] = 0.0;
00505             ad3[8] = 1.0;
00506         }
00507     if (ad[6] * ad[6] >= EPS1)
00508         if (ad[0] * ad[0] < EPS1) {
00509             ad8[0] = ad[0];
00510             ad8[1] = ad[1];
00511             ad8[2] = ad[2];
00512             ad[0] = ad[6];
00513             ad[1] = ad[7];
00514             ad[2] = ad[8];
00515             ad[6] = -ad8[0];
00516             ad[7] = -ad8[1];
00517             ad[8] = -ad8[2];
00518             ad8[0] = ad3[0];
00519             ad8[1] = ad3[1];
00520             ad8[2] = ad3[2];
00521             ad3[0] = ad3[6];
00522             ad3[1] = ad3[7];
00523             ad3[2] = ad3[8];
00524             ad3[6] = -ad8[0];
00525             ad3[7] = -ad8[1];
00526             ad3[8] = -ad8[2];
00527         } else {
00528             double d1 = 1.0 / sqrt(ad[0] * ad[0] + ad[6] * ad[6]);
00529             double d5 = ad[0] * d1;
00530             double d9 = ad[6] * d1;
00531             ad8[0] = d5 * ad[0] + d9 * ad[6];
00532             ad8[1] = d5 * ad[1] + d9 * ad[7];
00533             ad8[2] = d5 * ad[2] + d9 * ad[8];
00534             ad[6] = -d9 * ad[0] + d5 * ad[6];
00535             ad[7] = -d9 * ad[1] + d5 * ad[7];
00536             ad[8] = -d9 * ad[2] + d5 * ad[8];
00537             ad[0] = ad8[0];
00538             ad[1] = ad8[1];
00539             ad[2] = ad8[2];
00540             ad8[0] = d5 * ad3[0];
00541             ad8[1] = d5 * ad3[1];
00542             ad3[2] = d9;
00543             ad8[6] = -ad3[0] * d9;
00544             ad8[7] = -ad3[1] * d9;
00545             ad3[8] = d5;
00546             ad3[0] = ad8[0];
00547             ad3[1] = ad8[1];
00548             ad3[6] = ad8[6];
00549             ad3[7] = ad8[7];
00550         }
00551     if (ad[2] * ad[2] < EPS1) {
00552         set(1.0, ad4);
00553     } else
00554         if (ad[1] * ad[1] < EPS1) {
00555             ad8[2] = ad[2];
00556             ad8[5] = ad[5];
00557             ad8[8] = ad[8];
00558             ad[2] = -ad[1];
00559             ad[5] = -ad[4];
00560             ad[8] = -ad[7];
00561             ad[1] = ad8[2];
00562             ad[4] = ad8[5];
00563             ad[7] = ad8[8];
00564             ad4[0] = 1.0;
00565             ad4[1] = 0.0;
00566             ad4[2] = 0.0;
00567             ad4[3] = 0.0;
00568             ad4[4] = 0.0;
00569             ad4[5] = -1.0;
00570             ad4[6] = 0.0;
00571             ad4[7] = 1.0;
00572             ad4[8] = 0.0;
00573         } else {
00574             double d2 = 1.0 / sqrt(ad[1] * ad[1] + ad[2] * ad[2]);
00575             double d6 = ad[1] * d2;
00576             double d10 = ad[2] * d2;
00577             ad8[1] = d6 * ad[1] + d10 * ad[2];
00578             ad[2] = -d10 * ad[1] + d6 * ad[2];
00579             ad[1] = ad8[1];
00580             ad8[4] = d6 * ad[4] + d10 * ad[5];
00581             ad[5] = -d10 * ad[4] + d6 * ad[5];
00582             ad[4] = ad8[4];
00583             ad8[7] = d6 * ad[7] + d10 * ad[8];
00584             ad[8] = -d10 * ad[7] + d6 * ad[8];
00585             ad[7] = ad8[7];
00586             ad4[0] = 1.0;
00587             ad4[1] = 0.0;
00588             ad4[2] = 0.0;
00589             ad4[3] = 0.0;
00590             ad4[4] = d6;
00591             ad4[5] = -d10;
00592             ad4[6] = 0.0;
00593             ad4[7] = d10;
00594             ad4[8] = d6;
00595         }
00596     if (ad[7] * ad[7] >= EPS1)
00597         if (ad[4] * ad[4] < EPS1) {
00598             ad8[3] = ad[3];
00599             ad8[4] = ad[4];
00600             ad8[5] = ad[5];
00601             ad[3] = ad[6];
00602             ad[4] = ad[7];
00603             ad[5] = ad[8];
00604             ad[6] = -ad8[3];
00605             ad[7] = -ad8[4];
00606             ad[8] = -ad8[5];
00607             ad8[3] = ad3[3];
00608             ad8[4] = ad3[4];
00609             ad8[5] = ad3[5];
00610             ad3[3] = ad3[6];
00611             ad3[4] = ad3[7];
00612             ad3[5] = ad3[8];
00613             ad3[6] = -ad8[3];
00614             ad3[7] = -ad8[4];
00615             ad3[8] = -ad8[5];
00616         } else {
00617             double d3 = 1.0 / sqrt(ad[4] * ad[4] + ad[7] * ad[7]);
00618             double d7 = ad[4] * d3;
00619             double d11 = ad[7] * d3;
00620             ad8[3] = d7 * ad[3] + d11 * ad[6];
00621             ad[6] = -d11 * ad[3] + d7 * ad[6];
00622             ad[3] = ad8[3];
00623             ad8[4] = d7 * ad[4] + d11 * ad[7];
00624             ad[7] = -d11 * ad[4] + d7 * ad[7];
00625             ad[4] = ad8[4];
00626             ad8[5] = d7 * ad[5] + d11 * ad[8];
00627             ad[8] = -d11 * ad[5] + d7 * ad[8];
00628             ad[5] = ad8[5];
00629             ad8[3] = d7 * ad3[3] + d11 * ad3[6];
00630             ad3[6] = -d11 * ad3[3] + d7 * ad3[6];
00631             ad3[3] = ad8[3];
00632             ad8[4] = d7 * ad3[4] + d11 * ad3[7];
00633             ad3[7] = -d11 * ad3[4] + d7 * ad3[7];
00634             ad3[4] = ad8[4];
00635             ad8[5] = d7 * ad3[5] + d11 * ad3[8];
00636             ad3[8] = -d11 * ad3[5] + d7 * ad3[8];
00637             ad3[5] = ad8[5];
00638         }
00639     ad10[0] = ad[0];
00640     ad10[1] = ad[4];
00641     ad10[2] = ad[8];
00642     ad11[0] = ad[1];
00643     ad11[1] = ad[5];
00644     if (ad11[0] * ad11[0] < EPS1 && ad11[1] * ad11[1] < EPS1) {
00645         if (flag) {
00646             double xout, yout, zout;
00647             double xin, yin, zin;
00648             xin = yin = zin = 0;
00649             double d12 = 1.0;
00650             double d13 = 2.0;
00651             double d14 = 3.0;
00652             std::cout << "no QR iteration \n" << std::endl;
00653             ad7[0] = ad10[0];
00654             ad7[1] = 0.0;
00655             ad7[2] = 0.0;
00656             ad7[3] = 0.0;
00657             ad7[4] = ad10[1];
00658             ad7[5] = 0.0;
00659             ad7[6] = 0.0;
00660             ad7[7] = 0.0;
00661             ad7[8] = ad10[2];
00662 
00663             print_mat(ad7);
00664             print_mat(ad5);
00665             print_mat(ad6);
00666 
00667             mat_mul(ad5, ad7, ad8);
00668             mat_mul(ad8, ad6, ad8);
00669 
00670             print_mat(ad8);
00671             xout = d12 * ad8[0] + d13 * ad8[1] + d14 * ad8[2];
00672             yout = d12 * ad8[3] + d13 * ad8[4] + d14 * ad8[5];
00673             zout = d12 * ad8[6] + d13 * ad8[7] + d14 * ad8[8];
00674             if (Math::abs(xin - xout) > EPS3 || Math::abs(xin - xout) > EPS3 || Math::abs(xin - xout) > EPS3) {
00675                     std::cout << "\n   ERROR   in vec = " << xin << " " << yin << " " << zin << std::endl;
00676                     std::cout << "\n   ERROR   result = " << xout << " " << yout << " " << zout << std::endl;
00677             }
00678         }
00679     } else {
00680         compute_qr(ad10, ad11, ad3, ad4, flag);
00681     }
00682     ad12[0] = ad10[0];
00683     ad12[1] = ad10[1];
00684     ad12[2] = ad10[2];
00685     if (almostEqual(Math::abs(ad12[0]), 1.0) && almostEqual(Math::abs(ad12[1]), 1.0) && almostEqual(Math::abs(ad12[2]), 1.0)) {
00686         for (int j = 0; j < 3; j++)
00687             if (ad12[j] < 0.0)
00688                 l++;
00689 
00690         if (l == 0 || l == 2) {
00691             scale[0] = scale[1] = scale[2] = 1.0;
00692             for (int k = 0; k < 9; k++)
00693                 rot[k] = ad9[k];
00694 
00695             return;
00696         }
00697     }
00698     transpose_mat(ad3, ad5);
00699     transpose_mat(ad4, ad6);
00700     svdReorder(ad, ad5, ad6, ad12, rot, scale, flag);
00701 }
00702 
00703 double Matrix3SVD::d_sign(double d, double d1)
00704 {
00705     double d2 = d < 0.0 ? -d : d;
00706     return d1 < 0.0 ? -d2 : d2;
00707 }
00708 
00709 void Matrix3SVD::mat_mul(double ad[], double ad1[], double ad2[])
00710 {
00711     double ad3[9];
00712     ad3[0] = ad[0] * ad1[0] + ad[1] * ad1[3] + ad[2] * ad1[6];
00713     ad3[1] = ad[0] * ad1[1] + ad[1] * ad1[4] + ad[2] * ad1[7];
00714     ad3[2] = ad[0] * ad1[2] + ad[1] * ad1[5] + ad[2] * ad1[8];
00715     ad3[3] = ad[3] * ad1[0] + ad[4] * ad1[3] + ad[5] * ad1[6];
00716     ad3[4] = ad[3] * ad1[1] + ad[4] * ad1[4] + ad[5] * ad1[7];
00717     ad3[5] = ad[3] * ad1[2] + ad[4] * ad1[5] + ad[5] * ad1[8];
00718     ad3[6] = ad[6] * ad1[0] + ad[7] * ad1[3] + ad[8] * ad1[6];
00719     ad3[7] = ad[6] * ad1[1] + ad[7] * ad1[4] + ad[8] * ad1[7];
00720     ad3[8] = ad[6] * ad1[2] + ad[7] * ad1[5] + ad[8] * ad1[8];
00721     for (int i = 0; i < 9; i++)
00722         ad2[i] = ad3[i];
00723 
00724 }
00725 
00726 double Matrix3SVD::max(double d, double d1)
00727 {
00728     if (d > d1)
00729         return d;
00730     else
00731         return d1;
00732 }
00733 
00734 double Matrix3SVD::max3(double ad[])
00735 {
00736     if (ad[0] > ad[1])
00737         if (ad[0] > ad[2])
00738             return ad[0];
00739         else
00740             return ad[2];
00741     if (ad[1] > ad[2])
00742         return ad[1];
00743     else
00744         return ad[2];
00745 }
00746 
00747 double Matrix3SVD::min(double d, double d1)
00748 {
00749     if (d < d1)
00750         return d;
00751     else
00752         return d1;
00753 }
00754 
00755 void Matrix3SVD::print_det(double ad[])
00756 {
00757     double d = (ad[0] * ad[4] * ad[8] + ad[1] * ad[5] * ad[6] + ad[2] * ad[3] * ad[7]) - ad[2] * ad[4] * ad[6] - ad[0] * ad[5] * ad[7] - ad[1] * ad[3] * ad[8];
00758     std::cout << "det= " << d << std::endl;
00759 }
00760 
00761 void Matrix3SVD::print_mat(double ad[])
00762 {
00763     for (int i = 0; i < 3; i++)
00764         std::cout << ad[i * 3] << " " << ad[i * 3 + 1] << " " << ad[i * 3 + 2] << "\n";
00765     std::cout << std::endl;
00766 
00767 }
00768 void Matrix3SVD::svdReorder(double ad[], double ad1[], double ad2[], double ad3[], double ad4[], double scale[], bool flag)
00769 {
00770     int ai[3];
00771     double ad6[3];
00772     double ad7[9];
00773     if (ad3[0] < 0.0) {
00774         ad3[0] = -ad3[0];
00775         ad2[0] = -ad2[0];
00776         ad2[1] = -ad2[1];
00777         ad2[2] = -ad2[2];
00778     }
00779     if (ad3[1] < 0.0) {
00780         ad3[1] = -ad3[1];
00781         ad2[3] = -ad2[3];
00782         ad2[4] = -ad2[4];
00783         ad2[5] = -ad2[5];
00784     }
00785     if (ad3[2] < 0.0) {
00786         ad3[2] = -ad3[2];
00787         ad2[6] = -ad2[6];
00788         ad2[7] = -ad2[7];
00789         ad2[8] = -ad2[8];
00790     }
00791     mat_mul(ad1, ad2, ad7);
00792     if (almostEqual(Math::abs(ad3[0]), Math::abs(ad3[1])) && almostEqual(Math::abs(ad3[1]), Math::abs(ad3[2]))) {
00793         for (int j = 0; j < 9; j++)
00794             ad4[j] = ad7[j];
00795 
00796         for (int k = 0; k < 3; k++)
00797             scale[k] = ad3[k];
00798 
00799     } else {
00800         if (ad3[0] > ad3[1]) {
00801             if (ad3[0] > ad3[2]) {
00802                 if (ad3[2] > ad3[1]) {
00803                     ai[0] = 0;
00804                     ai[1] = 2;
00805                     ai[2] = 1;
00806                 } else {
00807                     ai[0] = 0;
00808                     ai[1] = 1;
00809                     ai[2] = 2;
00810                 }
00811             } else {
00812                 ai[0] = 2;
00813                 ai[1] = 0;
00814                 ai[2] = 1;
00815             }
00816         } else
00817             if (ad3[1] > ad3[2]) {
00818                 if (ad3[2] > ad3[0]) {
00819                     ai[0] = 1;
00820                     ai[1] = 2;
00821                     ai[2] = 0;
00822                 } else {
00823                     ai[0] = 1;
00824                     ai[1] = 0;
00825                     ai[2] = 2;
00826                 }
00827             } else {
00828                 ai[0] = 2;
00829                 ai[1] = 1;
00830                 ai[2] = 0;
00831             }
00832         ad6[0] = ad[0] * ad[0] + ad[1] * ad[1] + ad[2] * ad[2];
00833         ad6[1] = ad[3] * ad[3] + ad[4] * ad[4] + ad[5] * ad[5];
00834         ad6[2] = ad[6] * ad[6] + ad[7] * ad[7] + ad[8] * ad[8];
00835         unsigned char byte0;
00836         unsigned char byte1;
00837         unsigned char byte2;
00838         if (ad6[0] > ad6[1]) {
00839             if (ad6[0] > ad6[2]) {
00840                 if (ad6[2] > ad6[1]) {
00841                     byte0 = 0;
00842                     byte2 = 1;
00843                     byte1 = 2;
00844                 } else {
00845                     byte0 = 0;
00846                     byte1 = 1;
00847                     byte2 = 2;
00848                 }
00849             } else {
00850                 byte2 = 0;
00851                 byte0 = 1;
00852                 byte1 = 2;
00853             }
00854         } else
00855             if (ad6[1] > ad6[2]) {
00856                 if (ad6[2] > ad6[0]) {
00857                     byte1 = 0;
00858                     byte2 = 1;
00859                     byte0 = 2;
00860                 } else {
00861                     byte1 = 0;
00862                     byte0 = 1;
00863                     byte2 = 2;
00864                 }
00865             } else {
00866                 byte2 = 0;
00867                 byte1 = 1;
00868                 byte0 = 2;
00869             }
00870         int i = ai[byte0];
00871 
00872         scale[0] = ad3[i];
00873         i = ai[byte1];
00874         scale[1] = ad3[i];
00875         i = ai[byte2];
00876         scale[2] = ad3[i];
00877 
00878         i = ai[byte0];
00879         ad4[0] = ad7[i];
00880         i = ai[byte0] + 3;
00881         ad4[3] = ad7[i];
00882         i = ai[byte0] + 6;
00883         ad4[6] = ad7[i];
00884         i = ai[byte1];
00885         ad4[1] = ad7[i];
00886         i = ai[byte1] + 3;
00887         ad4[4] = ad7[i];
00888         i = ai[byte1] + 6;
00889         ad4[7] = ad7[i];
00890         i = ai[byte2];
00891         ad4[2] = ad7[i];
00892         i = ai[byte2] + 3;
00893         ad4[5] = ad7[i];
00894         i = ai[byte2] + 6;
00895         ad4[8] = ad7[i];
00896     }
00897 }
00898 
00899 void Matrix3SVD::transpose_mat(double ad[], double ad1[])
00900 {
00901     ad1[0] = ad[0];
00902     ad1[1] = ad[3];
00903     ad1[2] = ad[6];
00904     ad1[3] = ad[1];
00905     ad1[4] = ad[4];
00906     ad1[5] = ad[7];
00907     ad1[6] = ad[2];
00908     ad1[7] = ad[5];
00909     ad1[8] = ad[8];
00910 }
00911 
00912 void Matrix3SVD::copy(double ad[], double ad1[])
00913 {
00914     ad1[0] = ad[0];
00915     ad1[1] = ad[1];
00916     ad1[2] = ad[2];
00917     ad1[3] = ad[3];
00918     ad1[4] = ad[4];
00919     ad1[5] = ad[5];
00920     ad1[6] = ad[6];
00921     ad1[7] = ad[7];
00922     ad1[8] = ad[8];
00923 }
00924 
00925 void Matrix3SVD::set(double c, double ad[])
00926 {
00927     ad[0] = c;
00928     ad[1] = 0.0;
00929     ad[2] = 0.0;
00930     ad[3] = 0.0;
00931     ad[4] = c;
00932     ad[5] = 0.0;
00933     ad[6] = 0.0;
00934     ad[7] = 0.0;
00935     ad[8] = c;
00936 }
00937 
00938 void Matrix3SVD::test()
00939 {
00940     double ar[9];
00941     double cr[9];
00942     double rr[9];
00943     double sr[9];
00944 
00945     for(int i = 0; i < 9; i++)
00946         ar[i] = cr[i] = rr[i] = sr[i] = 0.0;
00947 
00948     ar[0] = 2 * 1.0;
00949     ar[1] = 0.0;
00950     ar[2] = 0.0;
00951     ar[3] = 0.0;
00952     ar[4] = 2 * cos(Math::toRadians(10));
00953     ar[5] = 2 * -sin(Math::toRadians(10));
00954     ar[6] = 0.0;
00955     ar[7] = 2 * sin(Math::toRadians(10));
00956     ar[8] = 2 * cos(Math::toRadians(10));
00957 
00958     compute_svd(ar, sr, rr, true);
00959     print_mat(ar);
00960     print_mat(sr);
00961     print_mat(rr);
00962 }
00963 

Generated on Thu Sep 29 13:39:45 2005 for vecmath by  doxygen 1.4.4