Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "_cxcore.h"
     43 
     44 /*F///////////////////////////////////////////////////////////////////////////////////////
     45 //    Names:      icvJacobiEigens_32f, icvJacobiEigens_64d
     46 //    Purpose:    Eigenvalues & eigenvectors calculation of a symmetric matrix:
     47 //                A Vi  =  Ei Vi
     48 //    Context:
     49 //    Parameters: A(n, n) - source symmetric matrix (n - rows & columns number),
     50 //                V(n, n) - matrix of its eigenvectors
     51 //                          (i-th row is an eigenvector Vi),
     52 //                E(n)    - vector of its eigenvalues
     53 //                          (i-th element is an eigenvalue Ei),
     54 //                eps     - accuracy of diagonalization.
     55 //
     56 //    Returns:
     57 //    CV_NO_ERROR or error code
     58 //    Notes:
     59 //        1. The functions destroy source matrix A, so if you need it further, you
     60 //           have to copy it before the processing.
     61 //        2. Eigenvalies and eigenvectors are sorted in Ei absolute value descending.
     62 //        3. Calculation time depends on eps value. If the time isn't very important,
     63 //           we recommend to set eps = 0.
     64 //F*/
     65 
     66 /*=========================== Single precision function ================================*/
     67 
     68 static CvStatus CV_STDCALL
     69 icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps)
     70 {
     71     int i, j, k, ind, iters = 0;
     72     float *AA = A, *VV = V;
     73     double Amax, anorm = 0, ax;
     74 
     75     if( A == NULL || V == NULL || E == NULL )
     76         return CV_NULLPTR_ERR;
     77     if( n <= 0 )
     78         return CV_BADSIZE_ERR;
     79     if( eps < DBL_EPSILON )
     80         eps = DBL_EPSILON;
     81 
     82     /*-------- Prepare --------*/
     83     for( i = 0; i < n; i++, VV += n, AA += n )
     84     {
     85         for( j = 0; j < i; j++ )
     86         {
     87             double Am = AA[j];
     88 
     89             anorm += Am * Am;
     90         }
     91         for( j = 0; j < n; j++ )
     92             VV[j] = 0.f;
     93         VV[i] = 1.f;
     94     }
     95 
     96     anorm = sqrt( anorm + anorm );
     97     ax = anorm * eps / n;
     98     Amax = anorm;
     99 
    100     while( Amax > ax && iters++ < 100 )
    101     {
    102         Amax /= n;
    103         do                      /* while (ind) */
    104         {
    105             int p, q;
    106             float *V1 = V, *A1 = A;
    107 
    108             ind = 0;
    109             for( p = 0; p < n - 1; p++, A1 += n, V1 += n )
    110             {
    111                 float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1);
    112 
    113                 for( q = p + 1; q < n; q++, A2 += n, V2 += n )
    114                 {
    115                     double x, y, c, s, c2, s2, a;
    116                     float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi;
    117 
    118                     if( fabs( Apq ) < Amax )
    119                         continue;
    120 
    121                     ind = 1;
    122 
    123                     /*---- Calculation of rotation angle's sine & cosine ----*/
    124                     App = A1[p];
    125                     Aqq = A2[q];
    126                     y = 5.0e-1 * (App - Aqq);
    127                     x = -Apq / sqrt( (double)Apq * Apq + (double)y * y );
    128                     if( y < 0.0 )
    129                         x = -x;
    130                     s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x )));
    131                     s2 = s * s;
    132                     c = sqrt( 1.0 - s2 );
    133                     c2 = c * c;
    134                     a = 2.0 * Apq * c * s;
    135 
    136                     /*---- Apq annulation ----*/
    137                     A3 = A;
    138                     for( i = 0; i < p; i++, A3 += n )
    139                     {
    140                         Aip = A3[p];
    141                         Aiq = A3[q];
    142                         Vpi = V1[i];
    143                         Vqi = V2[i];
    144                         A3[p] = (float) (Aip * c - Aiq * s);
    145                         A3[q] = (float) (Aiq * c + Aip * s);
    146                         V1[i] = (float) (Vpi * c - Vqi * s);
    147                         V2[i] = (float) (Vqi * c + Vpi * s);
    148                     }
    149                     for( ; i < q; i++, A3 += n )
    150                     {
    151                         Aip = A1[i];
    152                         Aiq = A3[q];
    153                         Vpi = V1[i];
    154                         Vqi = V2[i];
    155                         A1[i] = (float) (Aip * c - Aiq * s);
    156                         A3[q] = (float) (Aiq * c + Aip * s);
    157                         V1[i] = (float) (Vpi * c - Vqi * s);
    158                         V2[i] = (float) (Vqi * c + Vpi * s);
    159                     }
    160                     for( ; i < n; i++ )
    161                     {
    162                         Aip = A1[i];
    163                         Aiq = A2[i];
    164                         Vpi = V1[i];
    165                         Vqi = V2[i];
    166                         A1[i] = (float) (Aip * c - Aiq * s);
    167                         A2[i] = (float) (Aiq * c + Aip * s);
    168                         V1[i] = (float) (Vpi * c - Vqi * s);
    169                         V2[i] = (float) (Vqi * c + Vpi * s);
    170                     }
    171                     A1[p] = (float) (App * c2 + Aqq * s2 - a);
    172                     A2[q] = (float) (App * s2 + Aqq * c2 + a);
    173                     A1[q] = A2[p] = 0.0f;
    174                 }               /*q */
    175             }                   /*p */
    176         }
    177         while( ind );
    178         Amax /= n;
    179     }                           /* while ( Amax > ax ) */
    180 
    181     for( i = 0, k = 0; i < n; i++, k += n + 1 )
    182         E[i] = A[k];
    183     /*printf(" M = %d\n", M); */
    184 
    185     /* -------- ordering -------- */
    186     for( i = 0; i < n; i++ )
    187     {
    188         int m = i;
    189         float Em = (float) fabs( E[i] );
    190 
    191         for( j = i + 1; j < n; j++ )
    192         {
    193             float Ej = (float) fabs( E[j] );
    194 
    195             m = (Em < Ej) ? j : m;
    196             Em = (Em < Ej) ? Ej : Em;
    197         }
    198         if( m != i )
    199         {
    200             int l;
    201             float b = E[i];
    202 
    203             E[i] = E[m];
    204             E[m] = b;
    205             for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ )
    206             {
    207                 b = V[k];
    208                 V[k] = V[l];
    209                 V[l] = b;
    210             }
    211         }
    212     }
    213 
    214     return CV_NO_ERR;
    215 }
    216 
    217 /*=========================== Double precision function ================================*/
    218 
    219 static CvStatus CV_STDCALL
    220 icvJacobiEigens_64d(double *A, double *V, double *E, int n, double eps)
    221 {
    222     int i, j, k, p, q, ind, iters = 0;
    223     double *A1 = A, *V1 = V, *A2 = A, *V2 = V;
    224     double Amax = 0.0, anorm = 0.0, ax;
    225 
    226     if( A == NULL || V == NULL || E == NULL )
    227         return CV_NULLPTR_ERR;
    228     if( n <= 0 )
    229         return CV_BADSIZE_ERR;
    230     if( eps < DBL_EPSILON )
    231         eps = DBL_EPSILON;
    232 
    233     /*-------- Prepare --------*/
    234     for( i = 0; i < n; i++, V1 += n, A1 += n )
    235     {
    236         for( j = 0; j < i; j++ )
    237         {
    238             double Am = A1[j];
    239 
    240             anorm += Am * Am;
    241         }
    242         for( j = 0; j < n; j++ )
    243             V1[j] = 0.0;
    244         V1[i] = 1.0;
    245     }
    246 
    247     anorm = sqrt( anorm + anorm );
    248     ax = anorm * eps / n;
    249     Amax = anorm;
    250 
    251     while( Amax > ax && iters++ < 100 )
    252     {
    253         Amax /= n;
    254         do                      /* while (ind) */
    255         {
    256             ind = 0;
    257             A1 = A;
    258             V1 = V;
    259             for( p = 0; p < n - 1; p++, A1 += n, V1 += n )
    260             {
    261                 A2 = A + n * (p + 1);
    262                 V2 = V + n * (p + 1);
    263                 for( q = p + 1; q < n; q++, A2 += n, V2 += n )
    264                 {
    265                     double x, y, c, s, c2, s2, a;
    266                     double *A3, Apq, App, Aqq, App2, Aqq2, Aip, Aiq, Vpi, Vqi;
    267 
    268                     if( fabs( A1[q] ) < Amax )
    269                         continue;
    270                     Apq = A1[q];
    271 
    272                     ind = 1;
    273 
    274                     /*---- Calculation of rotation angle's sine & cosine ----*/
    275                     App = A1[p];
    276                     Aqq = A2[q];
    277                     y = 5.0e-1 * (App - Aqq);
    278                     x = -Apq / sqrt( Apq * Apq + (double)y * y );
    279                     if( y < 0.0 )
    280                         x = -x;
    281                     s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x )));
    282                     s2 = s * s;
    283                     c = sqrt( 1.0 - s2 );
    284                     c2 = c * c;
    285                     a = 2.0 * Apq * c * s;
    286 
    287                     /*---- Apq annulation ----*/
    288                     A3 = A;
    289                     for( i = 0; i < p; i++, A3 += n )
    290                     {
    291                         Aip = A3[p];
    292                         Aiq = A3[q];
    293                         Vpi = V1[i];
    294                         Vqi = V2[i];
    295                         A3[p] = Aip * c - Aiq * s;
    296                         A3[q] = Aiq * c + Aip * s;
    297                         V1[i] = Vpi * c - Vqi * s;
    298                         V2[i] = Vqi * c + Vpi * s;
    299                     }
    300                     for( ; i < q; i++, A3 += n )
    301                     {
    302                         Aip = A1[i];
    303                         Aiq = A3[q];
    304                         Vpi = V1[i];
    305                         Vqi = V2[i];
    306                         A1[i] = Aip * c - Aiq * s;
    307                         A3[q] = Aiq * c + Aip * s;
    308                         V1[i] = Vpi * c - Vqi * s;
    309                         V2[i] = Vqi * c + Vpi * s;
    310                     }
    311                     for( ; i < n; i++ )
    312                     {
    313                         Aip = A1[i];
    314                         Aiq = A2[i];
    315                         Vpi = V1[i];
    316                         Vqi = V2[i];
    317                         A1[i] = Aip * c - Aiq * s;
    318                         A2[i] = Aiq * c + Aip * s;
    319                         V1[i] = Vpi * c - Vqi * s;
    320                         V2[i] = Vqi * c + Vpi * s;
    321                     }
    322                     App2 = App * c2 + Aqq * s2 - a;
    323                     Aqq2 = App * s2 + Aqq * c2 + a;
    324                     A1[p] = App2;
    325                     A2[q] = Aqq2;
    326                     A1[q] = A2[p] = 0.0;
    327                 }               /*q */
    328             }                   /*p */
    329         }
    330         while( ind );
    331     }                           /* while ( Amax > ax ) */
    332 
    333     for( i = 0, k = 0; i < n; i++, k += n + 1 )
    334         E[i] = A[k];
    335 
    336     /* -------- ordering -------- */
    337     for( i = 0; i < n; i++ )
    338     {
    339         int m = i;
    340         double Em = fabs( E[i] );
    341 
    342         for( j = i + 1; j < n; j++ )
    343         {
    344             double Ej = fabs( E[j] );
    345 
    346             m = (Em < Ej) ? j : m;
    347             Em = (Em < Ej) ? Ej : Em;
    348         }
    349         if( m != i )
    350         {
    351             int l;
    352             double b = E[i];
    353 
    354             E[i] = E[m];
    355             E[m] = b;
    356             for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ )
    357             {
    358                 b = V[k];
    359                 V[k] = V[l];
    360                 V[l] = b;
    361             }
    362         }
    363     }
    364 
    365     return CV_NO_ERR;
    366 }
    367 
    368 
    369 CV_IMPL void
    370 cvEigenVV( CvArr* srcarr, CvArr* evectsarr, CvArr* evalsarr, double eps )
    371 {
    372 
    373     CV_FUNCNAME( "cvEigenVV" );
    374 
    375     __BEGIN__;
    376 
    377     CvMat sstub, *src = (CvMat*)srcarr;
    378     CvMat estub1, *evects = (CvMat*)evectsarr;
    379     CvMat estub2, *evals = (CvMat*)evalsarr;
    380 
    381     if( !CV_IS_MAT( src ))
    382         CV_CALL( src = cvGetMat( src, &sstub ));
    383 
    384     if( !CV_IS_MAT( evects ))
    385         CV_CALL( evects = cvGetMat( evects, &estub1 ));
    386 
    387     if( !CV_IS_MAT( evals ))
    388         CV_CALL( evals = cvGetMat( evals, &estub2 ));
    389 
    390     if( src->cols != src->rows )
    391         CV_ERROR( CV_StsUnmatchedSizes, "source is not quadratic matrix" );
    392 
    393     if( !CV_ARE_SIZES_EQ( src, evects) )
    394         CV_ERROR( CV_StsUnmatchedSizes, "eigenvectors matrix has inappropriate size" );
    395 
    396     if( (evals->rows != src->rows || evals->cols != 1) &&
    397         (evals->cols != src->rows || evals->rows != 1))
    398         CV_ERROR( CV_StsBadSize, "eigenvalues vector has inappropriate size" );
    399 
    400     if( !CV_ARE_TYPES_EQ( src, evects ) || !CV_ARE_TYPES_EQ( src, evals ))
    401         CV_ERROR( CV_StsUnmatchedFormats,
    402         "input matrix, eigenvalues and eigenvectors must have the same type" );
    403 
    404     if( !CV_IS_MAT_CONT( src->type & evals->type & evects->type ))
    405         CV_ERROR( CV_BadStep, "all the matrices must be continuous" );
    406 
    407     if( CV_MAT_TYPE(src->type) == CV_32FC1 )
    408     {
    409         IPPI_CALL( icvJacobiEigens_32f( src->data.fl,
    410                                         evects->data.fl,
    411                                         evals->data.fl, src->cols, (float)eps ));
    412 
    413     }
    414     else if( CV_MAT_TYPE(src->type) == CV_64FC1 )
    415     {
    416         IPPI_CALL( icvJacobiEigens_64d( src->data.db,
    417                                         evects->data.db,
    418                                         evals->data.db, src->cols, eps ));
    419     }
    420     else
    421     {
    422         CV_ERROR( CV_StsUnsupportedFormat, "Only 32fC1 and 64fC1 types are supported" );
    423     }
    424 
    425     CV_CHECK_NANS( evects );
    426     CV_CHECK_NANS( evals );
    427 
    428     __END__;
    429 }
    430 
    431 /* End of file */
    432