• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

jacobi.hh

00001 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00026 #ifndef MLN_MATH_JACOBI_HH
00027 # define MLN_MATH_JACOBI_HH
00028 
00030 
00031 # include <cmath>
00032 
00033 # include <mln/algebra/quat.hh>
00034 # include <mln/algebra/mat.hh>
00035 
00036 // from num. rec. in C
00037 // FIXME: what about numrec licence?
00038 
00039 
00040 namespace mln
00041 {
00042 
00043   namespace math
00044   {
00045 
00046     algebra::quat
00047     jacobi(algebra::mat<4u,4u,float> a);
00048 
00049 
00050 # ifndef MLN_INCLUDE_ONLY
00051 
00052   // FIXME: nD ?
00053 #define rotateJacobi(a,i,j,k,l) g=a(i,j);h=a(k,l);a(i,j)=g-s*(h+g*tau); \
00054     a(k,l)=h+s*(g-h*tau);
00055 
00056 
00057     algebra::quat
00058     jacobi(algebra::mat<4u,4u,float> a)
00059     {
00060       float dd, d[4];
00061       algebra::mat < 4, 4, float >v(literal::zero);
00062       int j, iq, ip, i = 0;
00063       float tresh, theta, tau, t, sm, s, h, g, c, b[4], z[4];
00064       for (ip = 0; ip < 4; ip++)
00065         {
00066           for (iq = 0; iq < 4; iq++)
00067             v(ip, iq) = 0.0f;
00068           v(ip, ip) = 1.0f;
00069         }
00070       for (ip = 0; ip < 4; ip++)
00071         {
00072           b[ip] = d[ip] = a(ip, ip);
00073           z[ip] = 0.0f;
00074         }
00075       while (1)
00076         {
00077           sm = 0.0f;
00078           for (ip = 0; ip < 3; ip++)
00079             {
00080               for (iq = ip + 1; iq < 4; iq++)
00081                 sm += std::fabs(a(ip, iq));
00082             }
00083           if (sm < 1e-12f)
00084             {                   // 1e-12
00085               dd = d[0];
00086               iq = 0;
00087               for (ip = 1; ip < 4; ip++)
00088                 if (d[ip] > dd)
00089                   {
00090                     iq = ip;
00091                     dd = d[ip];
00092                   }
00093               algebra::quat q(v(0, iq), v(1, iq), v(2, iq), v(3, iq));
00094               q.set_unit();
00095               return q;
00096             }
00097           if (i < 4)
00098             {
00099               i++;
00100               tresh = 0.0125f * sm;
00101             }
00102           else
00103             tresh = 0.0;
00104           for (ip = 0; ip < 3; ip++)
00105             {
00106               for (iq = ip + 1; iq < 4; iq++)
00107                 {
00108                   g = 100.0f * std::fabs(a(ip, iq));
00109                   if (i > 4 && (float)(std::fabs(d[ip]) + g) == (float)std::fabs(d[ip])
00110                       && (float)(std::fabs(d[iq]) + g) == (float)std::fabs(d[iq]))
00111                     a(ip, iq) = 0.0f;
00112                   else if (std::fabs(a(ip, iq)) > tresh)
00113                     {
00114                       h = d[iq] - d[ip];
00115                       if ((float)(std::fabs(h) + g) == (float)std::fabs(h)) // unsafe?
00116                         t = (a(ip, iq)) / h;
00117                       else
00118                         {
00119                           theta = 0.5f * h / (a(ip, iq));
00120                           t = 1.0f / (std::fabs(theta) + std::sqrt(1.0f +
00121                                                               theta * theta));
00122                           if (theta < 0.0f)
00123                             t = -t;
00124                         }
00125                       c = 1.0f / std::sqrt(1 + t * t);
00126                       s = t * c;
00127                       tau = s / (1.0f + c);
00128                       h = t * a(ip, iq);
00129                       z[ip] -= h;
00130                       z[iq] += h;
00131                       d[ip] -= h;
00132                       d[iq] += h;
00133                       a(ip, iq) = 0.0;
00134 
00135                       // DO *NOT* remove these semicolons!!
00136                       // rotateJacobi is a macro with 4 function calls.
00137                       for (j = 0; j <= ip - 1; j++)
00138                       {
00139                         rotateJacobi(a, j, ip, j, iq);
00140                       }
00141                       for (j = ip + 1; j <= iq - 1; j++)
00142                       {
00143                         rotateJacobi(a, ip, j, j, iq);
00144                       }
00145                       for (j = iq + 1; j < 4; j++)
00146                       {
00147                         rotateJacobi(a, ip, j, iq, j);
00148                       }
00149                       for (j = 0; j < 4; j++)
00150                       {
00151                         rotateJacobi(v, j, ip, j, iq);
00152                       }
00153                     }
00154                 }
00155             }
00156           for (ip = 0; ip < 4; ip++)
00157             {
00158               b[ip] += z[ip];
00159               d[ip] = b[ip];
00160               z[ip] = 0.0f;
00161             }
00162         }
00163     }
00164 
00165 # endif // ! MLN_INCLUDE_ONLY
00166 
00167   } // end of namespace math
00168 
00169 } // end of namespace mln
00170 
00171 
00172 #endif // ! MLN_MATH_JACOBI_HH

Generated on Tue Oct 4 2011 15:24:00 for Milena (Olena) by  doxygen 1.7.1