SVD.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00036 //
00037 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00038 //
00039 //  By downloading, copying, installing or using the software you agree to this license.
00040 //  If you do not agree to this license, do not download, install,
00041 //  copy or use the software.
00042 //
00043 //
00044 //                        Intel License Agreement
00045 //                For Open Source Computer Vision Library
00046 //
00047 // Copyright (C) 2000, Intel Corporation, all rights reserved.
00048 // Third party copyrights are property of their respective owners.
00049 //
00050 // Redistribution and use in source and binary forms, with or without modification,
00051 // are permitted provided that the following conditions are met:
00052 //
00053 //   * Redistribution's of source code must retain the above copyright notice,
00054 //     this list of conditions and the following disclaimer.
00055 //
00056 //   * Redistribution's in binary form must reproduce the above copyright notice,
00057 //     this list of conditions and the following disclaimer in the documentation
00058 //     and/or other materials provided with the distribution.
00059 //
00060 //   * The name of Intel Corporation may not be used to endorse or promote products
00061 //     derived from this software without specific prior written permission.
00062 //
00063 // This software is provided by the copyright holders and contributors "as is" and
00064 // any express or implied warranties, including, but not limited to, the implied
00065 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00066 // In no event shall the Intel Corporation or contributors be liable for any direct,
00067 // indirect, incidental, special, exemplary, or consequential damages
00068 // (including, but not limited to, procurement of substitute goods or services;
00069 // loss of use, data, or profits; or business interruption) however caused
00070 // and on any theory of liability, whether in contract, strict liability,
00071 // or tort (including negligence or otherwise) arising in any way out of
00072 // the use of this software, even if advised of the possibility of such damage.
00074 
00075 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00076 
00077 #include "Math/FloatMatrix.h"
00078 #include "Math/DoubleMatrix.h"
00079 #include "Math/LinearAlgebra.h"
00080 #include "Image/ImageProcessor.h"
00081 #include "Helpers/helpers.h"
00082 
00083 #include <math.h>
00084 #include <float.h>
00085 #include <string.h>
00086 #include <stdlib.h>
00087 #include <stdio.h>
00088 #include <assert.h>
00089 #include <algorithm>
00090 
00091 
00093 
00094 #define icvGivens_64f( n, x, y, c, s ) \
00095 {                                      \
00096     int _i;                            \
00097     double* _x = (x);                  \
00098     double* _y = (y);                  \
00099                                        \
00100     for( _i = 0; _i < n; _i++ )        \
00101     {                                  \
00102         double t0 = _x[_i];            \
00103         double t1 = _y[_i];            \
00104         _x[_i] = t0*c + t1*s;          \
00105         _y[_i] = -t0*s + t1*c;         \
00106     }                                  \
00107 }
00108 
00109 // Taken directly from OpenCV's headers.
00110 // CV_CHECK_NANS is just ignored.
00111 #define CV_CHECK_NANS( arr )
00112 #define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t))
00113 
00114 // Constants that can be passed as flags to cvSVD.
00115 #define CV_SVD_MODIFY_A (1 << 0)
00116 #define CV_SVD_U_T      (1 << 1)
00117 #define CV_SVD_V_T      (1 << 2)
00118 
00119 // This could be #defined to be alloca on UNIX systems.
00120 #define cvStackAlloc malloc
00121 
00122 namespace
00123 {
00124 
00125 /* y[0:m,0:n] += diag(a[0:1,0:m]) * x[0:m,0:n] */
00126 void
00127 icvMatrAXPY_64f( int m, int n, const double* x, int dx,
00128                  const double* a, double* y, int dy )
00129 {
00130     int i, j;
00131 
00132     for( i = 0; i < m; i++, x += dx, y += dy )
00133     {
00134         double s = a[i];
00135 
00136         for( j = 0; j <= n - 4; j += 4 )
00137         {
00138             double t0 = y[j]   + s*x[j];
00139             double t1 = y[j+1] + s*x[j+1];
00140             y[j]   = t0;
00141             y[j+1] = t1;
00142             t0 = y[j+2] + s*x[j+2];
00143             t1 = y[j+3] + s*x[j+3];
00144             y[j+2] = t0;
00145             y[j+3] = t1;
00146         }
00147 
00148         for( ; j < n; j++ ) y[j] += s*x[j];
00149     }
00150 }
00151 
00152 
00153 /* y[1:m,-1] = h*y[1:m,0:n]*x[0:1,0:n]'*x[-1]  (this is used for U&V reconstruction)
00154    y[1:m,0:n] += h*y[1:m,0:n]*x[0:1,0:n]'*x[0:1,0:n] */
00155 void
00156 icvMatrAXPY3_64f( int m, int n, const double* x, int l, double* y, double h )
00157 {
00158     int i, j;
00159 
00160     for( i = 1; i < m; i++ )
00161     {
00162         double s = 0;
00163 
00164         y += l;
00165 
00166         for( j = 0; j <= n - 4; j += 4 )
00167             s += x[j]*y[j] + x[j+1]*y[j+1] + x[j+2]*y[j+2] + x[j+3]*y[j+3];
00168 
00169         for( ; j < n; j++ )  s += x[j]*y[j];
00170 
00171         s *= h;
00172         y[-1] = s*x[-1];
00173 
00174         for( j = 0; j <= n - 4; j += 4 )
00175         {
00176             double t0 = y[j]   + s*x[j];
00177             double t1 = y[j+1] + s*x[j+1];
00178             y[j]   = t0;
00179             y[j+1] = t1;
00180             t0 = y[j+2] + s*x[j+2];
00181             t1 = y[j+3] + s*x[j+3];
00182             y[j+2] = t0;
00183             y[j+3] = t1;
00184         }
00185 
00186         for( ; j < n; j++ ) y[j] += s*x[j];
00187     }
00188 }
00189 
00190 
00191 #define icvGivens_32f( n, x, y, c, s ) \
00192 {                                      \
00193     int _i;                            \
00194     float* _x = (x);                   \
00195     float* _y = (y);                   \
00196                                        \
00197     for( _i = 0; _i < n; _i++ )        \
00198     {                                  \
00199         double t0 = _x[_i];            \
00200         double t1 = _y[_i];            \
00201         _x[_i] = (float)(t0*c + t1*s); \
00202         _y[_i] = (float)(-t0*s + t1*c);\
00203     }                                  \
00204 }
00205 
00206 void
00207 icvMatrAXPY_32f( int m, int n, const float* x, int dx,
00208                  const float* a, float* y, int dy )
00209 {
00210     int i, j;
00211 
00212     for( i = 0; i < m; i++, x += dx, y += dy )
00213     {
00214         double s = a[i];
00215 
00216         for( j = 0; j <= n - 4; j += 4 )
00217         {
00218             double t0 = y[j]   + s*x[j];
00219             double t1 = y[j+1] + s*x[j+1];
00220             y[j]   = (float)t0;
00221             y[j+1] = (float)t1;
00222             t0 = y[j+2] + s*x[j+2];
00223             t1 = y[j+3] + s*x[j+3];
00224             y[j+2] = (float)t0;
00225             y[j+3] = (float)t1;
00226         }
00227 
00228         for( ; j < n; j++ )
00229             y[j] = (float)(y[j] + s*x[j]);
00230     }
00231 }
00232 
00233 
00234 void
00235 icvMatrAXPY3_32f( int m, int n, const float* x, int l, float* y, double h )
00236 {
00237     int i, j;
00238 
00239     for( i = 1; i < m; i++ )
00240     {
00241         double s = 0;
00242         y += l;
00243 
00244         for( j = 0; j <= n - 4; j += 4 )
00245             s += x[j]*y[j] + x[j+1]*y[j+1] + x[j+2]*y[j+2] + x[j+3]*y[j+3];
00246 
00247         for( ; j < n; j++ )  s += x[j]*y[j];
00248 
00249         s *= h;
00250         y[-1] = (float)(s*x[-1]);
00251 
00252         for( j = 0; j <= n - 4; j += 4 )
00253         {
00254             double t0 = y[j]   + s*x[j];
00255             double t1 = y[j+1] + s*x[j+1];
00256             y[j]   = (float)t0;
00257             y[j+1] = (float)t1;
00258             t0 = y[j+2] + s*x[j+2];
00259             t1 = y[j+3] + s*x[j+3];
00260             y[j+2] = (float)t0;
00261             y[j+3] = (float)t1;
00262         }
00263 
00264         for( ; j < n; j++ ) y[j] = (float)(y[j] + s*x[j]);
00265     }
00266 }
00267 
00268 /* accurate hypotenuse calculation */
00269 double
00270 pythag( double a, double b )
00271 {
00272     a = fabs( a );
00273     b = fabs( b );
00274     if( a > b )
00275     {
00276         b /= a;
00277         a *= sqrt( 1. + b * b );
00278     }
00279     else if( b != 0 )
00280     {
00281         a /= b;
00282         a = b * sqrt( 1. + a * a );
00283     }
00284 
00285     return a;
00286 }
00287 
00288 /****************************************************************************************/
00289 /****************************************************************************************/
00290 
00291 #define MAX_ITERS  30
00292 
00293 void
00294 icvSVD_64f( double* a, int lda, int m, int n,
00295             double* w,
00296             double* uT, int lduT, int nu,
00297             double* vT, int ldvT,
00298             double* buffer )
00299 {
00300     double* e;
00301     double* temp;
00302     double *w1, *e1;
00303     double *hv;
00304     double ku0 = 0, kv0 = 0;
00305     double anorm = 0;
00306     double *a1, *u0 = uT, *v0 = vT;
00307     double scale, h;
00308     int i, j, k, l;
00309     int nm, m1, n1;
00310     int nv = n;
00311     int iters = 0;
00312     double* hv0 = (double*)cvStackAlloc( (m+2)*sizeof(hv0[0])) + 1; 
00313 
00314     e = buffer;
00315     w1 = w;
00316     e1 = e + 1;
00317     nm = n;
00318     
00319     temp = buffer + nm;
00320 
00321     memset( w, 0, nm * sizeof( w[0] ));
00322     memset( e, 0, nm * sizeof( e[0] ));
00323 
00324     m1 = m;
00325     n1 = n;
00326 
00327     /* transform a to bi-diagonal form */
00328     for( ;; )
00329     {
00330         int update_u;
00331         int update_v;
00332         
00333         if( m1 == 0 )
00334             break;
00335 
00336         scale = h = 0;
00337         update_u = uT && m1 > m - nu;
00338         hv = update_u ? uT : hv0;
00339 
00340         for( j = 0, a1 = a; j < m1; j++, a1 += lda )
00341         {
00342             double t = a1[0];
00343             scale += fabs( hv[j] = t );
00344         }
00345 
00346         if( scale != 0 )
00347         {
00348             double f = 1./scale, g, s = 0;
00349 
00350             for( j = 0; j < m1; j++ )
00351             {
00352                 double t = (hv[j] *= f);
00353                 s += t * t;
00354             }
00355 
00356             g = sqrt( s );
00357             f = hv[0];
00358             if( f >= 0 )
00359                 g = -g;
00360             hv[0] = f - g;
00361             h = 1. / (f * g - s);
00362 
00363             memset( temp, 0, n1 * sizeof( temp[0] ));
00364 
00365             /* calc temp[0:n-i] = a[i:m,i:n]'*hv[0:m-i] */
00366             icvMatrAXPY_64f( m1, n1 - 1, a + 1, lda, hv, temp + 1, 0 );
00367             for( k = 1; k < n1; k++ ) temp[k] *= h;
00368 
00369             /* modify a: a[i:m,i:n] = a[i:m,i:n] + hv[0:m-i]*temp[0:n-i]' */
00370             icvMatrAXPY_64f( m1, n1 - 1, temp + 1, 0, hv, a + 1, lda );
00371             *w1 = g*scale;
00372         }
00373         w1++;
00374 
00375         /* store -2/(hv'*hv) */
00376         if( update_u )
00377         {
00378             if( m1 == m )
00379                 ku0 = h;
00380             else
00381                 hv[-1] = h;
00382         }
00383 
00384         a++;
00385         n1--;
00386         if( vT )
00387             vT += ldvT + 1;
00388 
00389         if( n1 == 0 )
00390             break;
00391 
00392         scale = h = 0;
00393         update_v = vT && n1 > n - nv;
00394 
00395         hv = update_v ? vT : hv0;
00396 
00397         for( j = 0; j < n1; j++ )
00398         {
00399             double t = a[j];
00400             scale += fabs( hv[j] = t );
00401         }
00402 
00403         if( scale != 0 )
00404         {
00405             double f = 1./scale, g, s = 0;
00406 
00407             for( j = 0; j < n1; j++ )
00408             {
00409                 double t = (hv[j] *= f);
00410                 s += t * t;
00411             }
00412 
00413             g = sqrt( s );
00414             f = hv[0];
00415             if( f >= 0 )
00416                 g = -g;
00417             hv[0] = f - g;
00418             h = 1. / (f * g - s);
00419             hv[-1] = 0.;
00420 
00421             /* update a[i:m:i+1:n] = a[i:m,i+1:n] + (a[i:m,i+1:n]*hv[0:m-i])*... */
00422             icvMatrAXPY3_64f( m1, n1, hv, lda, a, h );
00423 
00424             *e1 = g*scale;
00425         }
00426         e1++;
00427 
00428         /* store -2/(hv'*hv) */
00429         if( update_v )
00430         {
00431             if( n1 == n )
00432                 kv0 = h;
00433             else
00434                 hv[-1] = h;
00435         }
00436 
00437         a += lda;
00438         m1--;
00439         if( uT )
00440             uT += lduT + 1;
00441     }
00442 
00443     m1 -= m1 != 0;
00444     n1 -= n1 != 0;
00445 
00446     /* accumulate left transformations */
00447     if( uT )
00448     {
00449         m1 = m - m1;
00450         uT = u0 + m1 * lduT;
00451         for( i = m1; i < nu; i++, uT += lduT )
00452         {
00453             memset( uT + m1, 0, (m - m1) * sizeof( uT[0] ));
00454             uT[i] = 1.;
00455         }
00456 
00457         for( i = m1 - 1; i >= 0; i-- )
00458         {
00459             double s;
00460             int lh = nu - i;
00461 
00462             l = m - i;
00463 
00464             hv = u0 + (lduT + 1) * i;
00465             h = i == 0 ? ku0 : hv[-1];
00466 
00467             //assert( h <= 0 );
00468             if (h > 0) printf("assert: h <= 0 not satisfied, h = %.2f\n", h);
00469 
00470             if( h != 0 )
00471             {
00472                 uT = hv;
00473                 icvMatrAXPY3_64f( lh, l-1, hv+1, lduT, uT+1, h );
00474 
00475                 s = hv[0] * h;
00476                 for( k = 0; k < l; k++ ) hv[k] *= s;
00477                 hv[0] += 1;
00478             }
00479             else
00480             {
00481                 for( j = 1; j < l; j++ )
00482                     hv[j] = 0;
00483                 for( j = 1; j < lh; j++ )
00484                     hv[j * lduT] = 0;
00485                 hv[0] = 1;
00486             }
00487         }
00488         uT = u0;
00489     }
00490 
00491     /* accumulate right transformations */
00492     if( vT )
00493     {
00494         n1 = n - n1;
00495         vT = v0 + n1 * ldvT;
00496         for( i = n1; i < nv; i++, vT += ldvT )
00497         {
00498             memset( vT + n1, 0, (n - n1) * sizeof( vT[0] ));
00499             vT[i] = 1.;
00500         }
00501 
00502         for( i = n1 - 1; i >= 0; i-- )
00503         {
00504             double s;
00505             int lh = nv - i;
00506 
00507             l = n - i;
00508             hv = v0 + (ldvT + 1) * i;
00509             h = i == 0 ? kv0 : hv[-1];
00510 
00511             //assert( h <= 0 );
00512             if (h > 0) printf("assert: h <= 0 not satisfied, h = %.2f (2)\n", h);
00513 
00514             if( h != 0 )
00515             {
00516                 vT = hv;
00517                 icvMatrAXPY3_64f( lh, l-1, hv+1, ldvT, vT+1, h );
00518 
00519                 s = hv[0] * h;
00520                 for( k = 0; k < l; k++ ) hv[k] *= s;
00521                 hv[0] += 1;
00522             }
00523             else
00524             {
00525                 for( j = 1; j < l; j++ )
00526                     hv[j] = 0;
00527                 for( j = 1; j < lh; j++ )
00528                     hv[j * ldvT] = 0;
00529                 hv[0] = 1;
00530             }
00531         }
00532         vT = v0;
00533     }
00534 
00535     for( i = 0; i < nm; i++ )
00536     {
00537         double tnorm = fabs( w[i] );
00538         tnorm += fabs( e[i] );
00539 
00540         if( anorm < tnorm )
00541             anorm = tnorm;
00542     }
00543 
00544     anorm *= DBL_EPSILON;
00545 
00546     /* diagonalization of the bidiagonal form */
00547     for( k = nm - 1; k >= 0; k-- )
00548     {
00549         double z = 0;
00550         iters = 0;
00551 
00552         for( ;; )               /* do iterations */
00553         {
00554             double c, s, f, g, x, y;
00555             int flag = 0;
00556 
00557             /* test for splitting */
00558             for( l = k; l >= 0; l-- )
00559             {
00560                 if( fabs(e[l]) <= anorm )
00561                 {
00562                     flag = 1;
00563                     break;
00564                 }
00565                 //assert( l > 0 );
00566                 if (l <= 0) printf("assert: l > 0 not satisfied, l = %i\n", l);
00567                 if( fabs(w[l - 1]) <= anorm )
00568                     break;
00569             }
00570 
00571             if( !flag )
00572             {
00573                 c = 0;
00574                 s = 1;
00575 
00576                 for( i = l; i <= k; i++ )
00577                 {
00578                     f = s * e[i];
00579 
00580                     e[i] *= c;
00581 
00582                     if( anorm + fabs( f ) == anorm )
00583                         break;
00584 
00585                     g = w[i];
00586                     h = pythag( f, g );
00587                     w[i] = h;
00588                     c = g / h;
00589                     s = -f / h;
00590 
00591                     if( uT )
00592                         icvGivens_64f( m, uT + lduT * (l - 1), uT + lduT * i, c, s );
00593                 }
00594             }
00595 
00596             z = w[k];
00597             if( l == k || iters++ == MAX_ITERS )
00598                 break;
00599 
00600             /* shift from bottom 2x2 minor */
00601             x = w[l];
00602             y = w[k - 1];
00603             g = e[k - 1];
00604             h = e[k];
00605             f = 0.5 * (((g + z) / h) * ((g - z) / y) + y / h - h / y);
00606             g = pythag( f, 1 );
00607             if( f < 0 )
00608                 g = -g;
00609             f = x - (z / x) * z + (h / x) * (y / (f + g) - h);
00610             /* next QR transformation */
00611             c = s = 1;
00612 
00613             for( i = l + 1; i <= k; i++ )
00614             {
00615                 g = e[i];
00616                 y = w[i];
00617                 h = s * g;
00618                 g *= c;
00619                 z = pythag( f, h );
00620                 e[i - 1] = z;
00621                 c = f / z;
00622                 s = h / z;
00623                 f = x * c + g * s;
00624                 g = -x * s + g * c;
00625                 h = y * s;
00626                 y *= c;
00627 
00628                 if( vT )
00629                     icvGivens_64f( n, vT + ldvT * (i - 1), vT + ldvT * i, c, s );
00630 
00631                 z = pythag( f, h );
00632                 w[i - 1] = z;
00633 
00634                 /* rotation can be arbitrary if z == 0 */
00635                 if( z != 0 )
00636                 {
00637                     c = f / z;
00638                     s = h / z;
00639                 }
00640                 f = c * g + s * y;
00641                 x = -s * g + c * y;
00642 
00643                 if( uT )
00644                     icvGivens_64f( m, uT + lduT * (i - 1), uT + lduT * i, c, s );
00645             }
00646 
00647             e[l] = 0;
00648             e[k] = f;
00649             w[k] = x;
00650         }                       /* end of iteration loop */
00651 
00652         if( iters > MAX_ITERS )
00653             break;
00654 
00655         if( z < 0 )
00656         {
00657             w[k] = -z;
00658             if( vT )
00659             {
00660                 for( j = 0; j < n; j++ )
00661                     vT[j + k * ldvT] = -vT[j + k * ldvT];
00662             }
00663         }
00664     }                           /* end of diagonalization loop */
00665 
00666     /* sort singular values and corresponding values */
00667     for( i = 0; i < nm; i++ )
00668     {
00669         k = i;
00670         for( j = i + 1; j < nm; j++ )
00671             if( w[k] < w[j] )
00672                 k = j;
00673 
00674         if( k != i )
00675         {
00676             double t;
00677             CV_SWAP( w[i], w[k], t );
00678 
00679             if( vT )
00680                 for( j = 0; j < n; j++ )
00681                     CV_SWAP( vT[j + ldvT*k], vT[j + ldvT*i], t );
00682 
00683             if( uT )
00684                 for( j = 0; j < m; j++ )
00685                     CV_SWAP( uT[j + lduT*k], uT[j + lduT*i], t );
00686         }
00687     }
00688 
00689         free(hv0 - 1);
00690 }
00691 
00692 
00693 void
00694 icvSVD_32f( float* a, int lda, int m, int n,
00695             float* w,
00696             float* uT, int lduT, int nu,
00697             float* vT, int ldvT,
00698             float* buffer )
00699 {
00700     float* e;
00701     float* temp;
00702     float *w1, *e1;
00703     float *hv;
00704     double ku0 = 0, kv0 = 0;
00705     double anorm = 0;
00706     float *a1, *u0 = uT, *v0 = vT;
00707     double scale, h;
00708     int i, j, k, l;
00709     int nm, m1, n1;
00710     int nv = n;
00711     int iters = 0;
00712     float* hv0 = (float*)cvStackAlloc( (m+2)*sizeof(hv0[0])) + 1;
00713 
00714     e = buffer;
00715 
00716     w1 = w;
00717     e1 = e + 1;
00718     nm = n;
00719     
00720     temp = buffer + nm;
00721 
00722     memset( w, 0, nm * sizeof( w[0] ));
00723     memset( e, 0, nm * sizeof( e[0] ));
00724 
00725     m1 = m;
00726     n1 = n;
00727 
00728     /* transform a to bi-diagonal form */
00729     for( ;; )
00730     {
00731         int update_u;
00732         int update_v;
00733         
00734         if( m1 == 0 )
00735             break;
00736 
00737         scale = h = 0;
00738 
00739         update_u = uT && m1 > m - nu;
00740         hv = update_u ? uT : hv0;
00741 
00742         for( j = 0, a1 = a; j < m1; j++, a1 += lda )
00743         {
00744             double t = a1[0];
00745             scale += fabs( hv[j] = (float)t );
00746         }
00747 
00748         if( scale != 0 )
00749         {
00750             double f = 1./scale, g, s = 0;
00751 
00752             for( j = 0; j < m1; j++ )
00753             {
00754                 double t = (hv[j] = (float)(hv[j]*f));
00755                 s += t * t;
00756             }
00757 
00758             g = sqrt( s );
00759             f = hv[0];
00760             if( f >= 0 )
00761                 g = -g;
00762             hv[0] = (float)(f - g);
00763             h = 1. / (f * g - s);
00764 
00765             memset( temp, 0, n1 * sizeof( temp[0] ));
00766 
00767             /* calc temp[0:n-i] = a[i:m,i:n]'*hv[0:m-i] */
00768             icvMatrAXPY_32f( m1, n1 - 1, a + 1, lda, hv, temp + 1, 0 );
00769 
00770             for( k = 1; k < n1; k++ ) temp[k] = (float)(temp[k]*h);
00771 
00772             /* modify a: a[i:m,i:n] = a[i:m,i:n] + hv[0:m-i]*temp[0:n-i]' */
00773             icvMatrAXPY_32f( m1, n1 - 1, temp + 1, 0, hv, a + 1, lda );
00774             *w1 = (float)(g*scale);
00775         }
00776         w1++;
00777         
00778         /* store -2/(hv'*hv) */
00779         if( update_u )
00780         {
00781             if( m1 == m )
00782                 ku0 = h;
00783             else
00784                 hv[-1] = (float)h;
00785         }
00786 
00787         a++;
00788         n1--;
00789         if( vT )
00790             vT += ldvT + 1;
00791 
00792         if( n1 == 0 )
00793             break;
00794 
00795         scale = h = 0;
00796         update_v = vT && n1 > n - nv;
00797         hv = update_v ? vT : hv0;
00798 
00799         for( j = 0; j < n1; j++ )
00800         {
00801             double t = a[j];
00802             scale += fabs( hv[j] = (float)t );
00803         }
00804 
00805         if( scale != 0 )
00806         {
00807             double f = 1./scale, g, s = 0;
00808 
00809             for( j = 0; j < n1; j++ )
00810             {
00811                 double t = (hv[j] = (float)(hv[j]*f));
00812                 s += t * t;
00813             }
00814 
00815             g = sqrt( s );
00816             f = hv[0];
00817             if( f >= 0 )
00818                 g = -g;
00819             hv[0] = (float)(f - g);
00820             h = 1. / (f * g - s);
00821             hv[-1] = 0.f;
00822 
00823             /* update a[i:m:i+1:n] = a[i:m,i+1:n] + (a[i:m,i+1:n]*hv[0:m-i])*... */
00824             icvMatrAXPY3_32f( m1, n1, hv, lda, a, h );
00825 
00826             *e1 = (float)(g*scale);
00827         }
00828         e1++;
00829 
00830         /* store -2/(hv'*hv) */
00831         if( update_v )
00832         {
00833             if( n1 == n )
00834                 kv0 = h;
00835             else
00836                 hv[-1] = (float)h;
00837         }
00838 
00839         a += lda;
00840         m1--;
00841         if( uT )
00842             uT += lduT + 1;
00843     }
00844 
00845     m1 -= m1 != 0;
00846     n1 -= n1 != 0;
00847 
00848     /* accumulate left transformations */
00849     if( uT )
00850     {
00851         m1 = m - m1;
00852         uT = u0 + m1 * lduT;
00853         for( i = m1; i < nu; i++, uT += lduT )
00854         {
00855             memset( uT + m1, 0, (m - m1) * sizeof( uT[0] ));
00856             uT[i] = 1.;
00857         }
00858 
00859         for( i = m1 - 1; i >= 0; i-- )
00860         {
00861             double s;
00862             int lh = nu - i;
00863 
00864             l = m - i;
00865 
00866             hv = u0 + (lduT + 1) * i;
00867             h = i == 0 ? ku0 : hv[-1];
00868 
00869             //assert( h <= 0 );
00870             if (h > 0) printf("assert: h <= 0 not satisfied, h = %.2f (3)\n", h);
00871 
00872             if( h != 0 )
00873             {
00874                 uT = hv;
00875                 icvMatrAXPY3_32f( lh, l-1, hv+1, lduT, uT+1, h );
00876 
00877                 s = hv[0] * h;
00878                 for( k = 0; k < l; k++ ) hv[k] = (float)(hv[k]*s);
00879                 hv[0] += 1;
00880             }
00881             else
00882             {
00883                 for( j = 1; j < l; j++ )
00884                     hv[j] = 0;
00885                 for( j = 1; j < lh; j++ )
00886                     hv[j * lduT] = 0;
00887                 hv[0] = 1;
00888             }
00889         }
00890         uT = u0;
00891     }
00892 
00893     /* accumulate right transformations */
00894     if( vT )
00895     {
00896         n1 = n - n1;
00897         vT = v0 + n1 * ldvT;
00898         for( i = n1; i < nv; i++, vT += ldvT )
00899         {
00900             memset( vT + n1, 0, (n - n1) * sizeof( vT[0] ));
00901             vT[i] = 1.;
00902         }
00903 
00904         for( i = n1 - 1; i >= 0; i-- )
00905         {
00906             double s;
00907             int lh = nv - i;
00908 
00909             l = n - i;
00910             hv = v0 + (ldvT + 1) * i;
00911             h = i == 0 ? kv0 : hv[-1];
00912 
00913             //assert( h <= 0 );
00914             if (h > 0) printf("assert: h <= 0 not satisfied, h = %.2f (4)\n", h);
00915 
00916             if( h != 0 )
00917             {
00918                 vT = hv;
00919                 icvMatrAXPY3_32f( lh, l-1, hv+1, ldvT, vT+1, h );
00920 
00921                 s = hv[0] * h;
00922                 for( k = 0; k < l; k++ ) hv[k] = (float)(hv[k]*s);
00923                 hv[0] += 1;
00924             }
00925             else
00926             {
00927                 for( j = 1; j < l; j++ )
00928                     hv[j] = 0;
00929                 for( j = 1; j < lh; j++ )
00930                     hv[j * ldvT] = 0;
00931                 hv[0] = 1;
00932             }
00933         }
00934         vT = v0;
00935     }
00936 
00937     for( i = 0; i < nm; i++ )
00938     {
00939         double tnorm = fabs( w[i] );
00940         tnorm += fabs( e[i] );
00941 
00942         if( anorm < tnorm )
00943             anorm = tnorm;
00944     }
00945 
00946     anorm *= FLT_EPSILON;
00947 
00948     /* diagonalization of the bidiagonal form */
00949     for( k = nm - 1; k >= 0; k-- )
00950     {
00951         double z = 0;
00952         iters = 0;
00953 
00954         for( ;; )               /* do iterations */
00955         {
00956             double c, s, f, g, x, y;
00957             int flag = 0;
00958 
00959             /* test for splitting */
00960             for( l = k; l >= 0; l-- )
00961             {
00962                 if( fabs( e[l] ) <= anorm )
00963                 {
00964                     flag = 1;
00965                     break;
00966                 }
00967                 //assert( l > 0 );
00968                 if (l <= 0) printf("assert: l > 0 not satisfied, l = %i\n", l);
00969                 
00970                 if( fabs( w[l - 1] ) <= anorm )
00971                     break;
00972             }
00973 
00974             if( !flag )
00975             {
00976                 c = 0;
00977                 s = 1;
00978 
00979                 for( i = l; i <= k; i++ )
00980                 {
00981                     f = s * e[i];
00982                     e[i] = (float)(e[i]*c);
00983 
00984                     if( anorm + fabs( f ) == anorm )
00985                         break;
00986 
00987                     g = w[i];
00988                     h = pythag( f, g );
00989                     w[i] = (float)h;
00990                     c = g / h;
00991                     s = -f / h;
00992 
00993                     if( uT )
00994                         icvGivens_32f( m, uT + lduT * (l - 1), uT + lduT * i, c, s );
00995                 }
00996             }
00997 
00998             z = w[k];
00999             if( l == k || iters++ == MAX_ITERS )
01000                 break;
01001 
01002             /* shift from bottom 2x2 minor */
01003             x = w[l];
01004             y = w[k - 1];
01005             g = e[k - 1];
01006             h = e[k];
01007             f = 0.5 * (((g + z) / h) * ((g - z) / y) + y / h - h / y);
01008             g = pythag( f, 1 );
01009             if( f < 0 )
01010                 g = -g;
01011             f = x - (z / x) * z + (h / x) * (y / (f + g) - h);
01012             /* next QR transformation */
01013             c = s = 1;
01014 
01015             for( i = l + 1; i <= k; i++ )
01016             {
01017                 g = e[i];
01018                 y = w[i];
01019                 h = s * g;
01020                 g *= c;
01021                 z = pythag( f, h );
01022                 e[i - 1] = (float)z;
01023                 c = f / z;
01024                 s = h / z;
01025                 f = x * c + g * s;
01026                 g = -x * s + g * c;
01027                 h = y * s;
01028                 y *= c;
01029 
01030                 if( vT )
01031                     icvGivens_32f( n, vT + ldvT * (i - 1), vT + ldvT * i, c, s );
01032 
01033                 z = pythag( f, h );
01034                 w[i - 1] = (float)z;
01035 
01036                 /* rotation can be arbitrary if z == 0 */
01037                 if( z != 0 )
01038                 {
01039                     c = f / z;
01040                     s = h / z;
01041                 }
01042                 f = c * g + s * y;
01043                 x = -s * g + c * y;
01044 
01045                 if( uT )
01046                     icvGivens_32f( m, uT + lduT * (i - 1), uT + lduT * i, c, s );
01047             }
01048 
01049             e[l] = 0;
01050             e[k] = (float)f;
01051             w[k] = (float)x;
01052         }                       /* end of iteration loop */
01053 
01054         if( iters > MAX_ITERS )
01055             break;
01056 
01057         if( z < 0 )
01058         {
01059             w[k] = (float)(-z);
01060             if( vT )
01061             {
01062                 for( j = 0; j < n; j++ )
01063                     vT[j + k * ldvT] = -vT[j + k * ldvT];
01064             }
01065         }
01066     }                           /* end of diagonalization loop */
01067 
01068     /* sort singular values and corresponding vectors */
01069     for( i = 0; i < nm; i++ )
01070     {
01071         k = i;
01072         for( j = i + 1; j < nm; j++ )
01073             if( w[k] < w[j] )
01074                 k = j;
01075 
01076         if( k != i )
01077         {
01078             float t;
01079             CV_SWAP( w[i], w[k], t );
01080 
01081             if( vT )
01082                 for( j = 0; j < n; j++ )
01083                     CV_SWAP( vT[j + ldvT*k], vT[j + ldvT*i], t );
01084 
01085             if( uT )
01086                 for( j = 0; j < m; j++ )
01087                     CV_SWAP( uT[j + lduT*k], uT[j + lduT*i], t );
01088         }
01089     }
01090 
01091         free(hv0 - 1);
01092 }
01093 
01094 
01095 void
01096 icvSVBkSb_64f( int m, int n, const double* w,
01097                const double* uT, int lduT,
01098                const double* vT, int ldvT,
01099                const double* b, int ldb, int nb,
01100                double* x, int ldx, double* buffer )
01101 {
01102     double threshold = 0;
01103     int i, j, nm = MY_MIN( m, n );
01104 
01105     if( !b )
01106         nb = m;
01107 
01108     for( i = 0; i < n; i++ )
01109         memset( x + i*ldx, 0, nb*sizeof(x[0]));
01110 
01111     for( i = 0; i < nm; i++ )
01112         threshold += w[i];
01113     threshold *= 2*DBL_EPSILON;
01114 
01115     /* vT * inv(w) * uT * b */
01116     for( i = 0; i < nm; i++, uT += lduT, vT += ldvT )
01117     {
01118         double wi = w[i];
01119 
01120         if( wi > threshold )
01121         {
01122             wi = 1./wi;
01123 
01124             if( nb == 1 )
01125             {
01126                 double s = 0;
01127                 if( b )
01128                 {
01129                     if( ldb == 1 )
01130                     {
01131                         for( j = 0; j <= m - 4; j += 4 )
01132                             s += uT[j]*b[j] + uT[j+1]*b[j+1] + uT[j+2]*b[j+2] + uT[j+3]*b[j+3];
01133                         for( ; j < m; j++ )
01134                             s += uT[j]*b[j];
01135                     }
01136                     else
01137                     {
01138                         for( j = 0; j < m; j++ )
01139                             s += uT[j]*b[j*ldb];
01140                     }
01141                 }
01142                 else
01143                     s = uT[0];
01144                 s *= wi;
01145                 if( ldx == 1 )
01146                 {
01147                     for( j = 0; j <= n - 4; j += 4 )
01148                     {
01149                         double t0 = x[j] + s*vT[j];
01150                         double t1 = x[j+1] + s*vT[j+1];
01151                         x[j] = t0;
01152                         x[j+1] = t1;
01153                         t0 = x[j+2] + s*vT[j+2];
01154                         t1 = x[j+3] + s*vT[j+3];
01155                         x[j+2] = t0;
01156                         x[j+3] = t1;
01157                     }
01158 
01159                     for( ; j < n; j++ )
01160                         x[j] += s*vT[j];
01161                 }
01162                 else
01163                 {
01164                     for( j = 0; j < n; j++ )
01165                         x[j*ldx] += s*vT[j];
01166                 }
01167             }
01168             else
01169             {
01170                 if( b )
01171                 {
01172                     memset( buffer, 0, nb*sizeof(buffer[0]));
01173                     icvMatrAXPY_64f( m, nb, b, ldb, uT, buffer, 0 );
01174                     for( j = 0; j < nb; j++ )
01175                         buffer[j] *= wi;
01176                 }
01177                 else
01178                 {
01179                     for( j = 0; j < nb; j++ )
01180                         buffer[j] = uT[j]*wi;
01181                 }
01182                 icvMatrAXPY_64f( n, nb, buffer, 0, vT, x, ldx );
01183             }
01184         }
01185     }
01186 }
01187 
01188 
01189 void
01190 icvSVBkSb_32f( int m, int n, const float* w,
01191                const float* uT, int lduT,
01192                const float* vT, int ldvT,
01193                const float* b, int ldb, int nb,
01194                float* x, int ldx, float* buffer )
01195 {
01196     float threshold = 0.f;
01197     int i, j, nm = MY_MIN( m, n );
01198 
01199     if( !b )
01200         nb = m;
01201 
01202     for( i = 0; i < n; i++ )
01203         memset( x + i*ldx, 0, nb*sizeof(x[0]));
01204 
01205     for( i = 0; i < nm; i++ )
01206         threshold += w[i];
01207     threshold *= 2*FLT_EPSILON;
01208 
01209     /* vT * inv(w) * uT * b */
01210     for( i = 0; i < nm; i++, uT += lduT, vT += ldvT )
01211     {
01212         double wi = w[i];
01213         
01214         if( wi > threshold )
01215         {
01216             wi = 1./wi;
01217 
01218             if( nb == 1 )
01219             {
01220                 double s = 0;
01221                 if( b )
01222                 {
01223                     if( ldb == 1 )
01224                     {
01225                         for( j = 0; j <= m - 4; j += 4 )
01226                             s += uT[j]*b[j] + uT[j+1]*b[j+1] + uT[j+2]*b[j+2] + uT[j+3]*b[j+3];
01227                         for( ; j < m; j++ )
01228                             s += uT[j]*b[j];
01229                     }
01230                     else
01231                     {
01232                         for( j = 0; j < m; j++ )
01233                             s += uT[j]*b[j*ldb];
01234                     }
01235                 }
01236                 else
01237                     s = uT[0];
01238                 s *= wi;
01239 
01240                 if( ldx == 1 )
01241                 {
01242                     for( j = 0; j <= n - 4; j += 4 )
01243                     {
01244                         double t0 = x[j] + s*vT[j];
01245                         double t1 = x[j+1] + s*vT[j+1];
01246                         x[j] = (float)t0;
01247                         x[j+1] = (float)t1;
01248                         t0 = x[j+2] + s*vT[j+2];
01249                         t1 = x[j+3] + s*vT[j+3];
01250                         x[j+2] = (float)t0;
01251                         x[j+3] = (float)t1;
01252                     }
01253 
01254                     for( ; j < n; j++ )
01255                         x[j] = (float)(x[j] + s*vT[j]);
01256                 }
01257                 else
01258                 {
01259                     for( j = 0; j < n; j++ )
01260                         x[j*ldx] = (float)(x[j*ldx] + s*vT[j]);
01261                 }
01262             }
01263             else
01264             {
01265                 if( b )
01266                 {
01267                     memset( buffer, 0, nb*sizeof(buffer[0]));
01268                     icvMatrAXPY_32f( m, nb, b, ldb, uT, buffer, 0 );
01269                     for( j = 0; j < nb; j++ )
01270                         buffer[j] = (float)(buffer[j]*wi);
01271                 }
01272                 else
01273                 {
01274                     for( j = 0; j < nb; j++ )
01275                         buffer[j] = (float)(uT[j]*wi);
01276                 }
01277                 icvMatrAXPY_32f( n, nb, buffer, 0, vT, x, ldx );
01278             }
01279         }
01280     }
01281 }
01282 
01283 
01284 void
01285 cvSVD( const CFloatMatrix* aarr, CFloatMatrix* warr, CFloatMatrix* uarr, CFloatMatrix* varr, int flags )
01286 {
01287         typedef unsigned char uchar;
01288 
01289     uchar* buffer = 0;
01290     //int local_alloc = 0;
01291 
01292     CFloatMatrix tmat;
01293         CFloatMatrix ustub, vstub;
01294 
01295         const CFloatMatrix *a = aarr;
01296         CFloatMatrix *w = warr;
01297 
01298     uchar* tw = 0;
01299     int a_buf_offset = 0, u_buf_offset = 0, buf_size, pix_size;
01300     int temp_u = 0, /* temporary storage for U is needed */
01301         t_svd; /* special case: a->rows < a->columns */
01302     int m, n;
01303     int w_rows, w_cols;
01304     int u_rows = 0, u_cols = 0;
01305     int w_is_mat = 0;
01306 
01307     if( a->rows >= a->columns )
01308     {
01309         m = a->rows;
01310         n = a->columns;
01311         w_rows = w->rows;
01312         w_cols = w->columns;
01313         t_svd = 0;
01314     }
01315     else
01316     {
01317         CFloatMatrix* t;
01318         CV_SWAP( uarr, varr, t );
01319 
01320         flags = (flags & CV_SVD_U_T ? CV_SVD_V_T : 0)|
01321                 (flags & CV_SVD_V_T ? CV_SVD_U_T : 0);
01322         m = a->columns;
01323         n = a->rows;
01324         w_rows = w->columns;
01325         w_cols = w->rows;
01326         t_svd = 1;
01327     }
01328 
01329         CFloatMatrix *u = uarr;
01330         CFloatMatrix *v = varr;
01331 
01332     w_is_mat = w_cols > 1 && w_rows > 1;
01333         if (!w_is_mat && w_cols + w_rows - 1 == n)
01334                 tw = (uchar*) w->data;
01335 
01336     if( u )
01337     {
01338         if( !(flags & CV_SVD_U_T) )
01339         {
01340             u_rows = u->rows;
01341             u_cols = u->columns;
01342         }
01343         else
01344         {
01345             u_rows = u->columns;
01346             u_cols = u->rows;
01347         }
01348 
01349         if( u_rows != m || (u_cols != m && u_cols != n))
01350             !t_svd ? printf( "U matrix has unappropriate size" ) : printf( "V matrix has unappropriate size" );
01351             
01352         temp_u = (u_rows != u_cols && !(flags & CV_SVD_U_T)) || u->data == a->data;
01353 
01354         if( w_is_mat && u_cols != w_rows )
01355             !t_svd ? printf( "U and W have incompatible sizes" ) : printf( "V and W have incompatible sizes" );
01356     }
01357     else
01358     {
01359         u = &ustub;
01360                 u->rows = 0;
01361                 u->columns = 0;
01362         u->data = 0;
01363     }
01364 
01365     if( v )
01366     {
01367         int v_rows, v_cols;
01368 
01369         if( !(flags & CV_SVD_V_T) )
01370         {
01371             v_rows = v->rows;
01372             v_cols = v->columns;
01373         }
01374         else
01375         {
01376             v_rows = v->columns;
01377             v_cols = v->rows;
01378         }
01379 
01380         if( v_rows != n || v_cols != n )
01381             t_svd ? printf( "U matrix has unappropriate size") : printf("V matrix has unappropriate size" );
01382 
01383         if( w_is_mat && w_cols != v_cols )
01384             t_svd ? printf( "U and W have incompatible sizes") : printf("V and W have incompatible sizes" );
01385     }
01386     else
01387     {
01388         v = &vstub;
01389                 v->rows = 0;
01390                 v->columns = 0;
01391         v->data = 0;
01392     }
01393 
01394     pix_size = sizeof(float);
01395     buf_size = n*2 + m;
01396 
01397     if( !(flags & CV_SVD_MODIFY_A) )
01398     {
01399         a_buf_offset = buf_size;
01400         buf_size += a->rows*a->columns;
01401     }
01402 
01403     if( temp_u )
01404     {
01405         u_buf_offset = buf_size;
01406         buf_size += u->rows*u->columns;
01407     }
01408 
01409     buf_size *= pix_size;
01410 
01411     buffer = (uchar*)malloc( buf_size );
01412     
01413     if( !(flags & CV_SVD_MODIFY_A) )
01414     {
01415                 tmat.rows = m;
01416                 tmat.columns = n;
01417                 tmat.data = (float *)(buffer + a_buf_offset * pix_size);
01418 
01419         if( !t_svd )
01420                         ImageProcessor::CopyMatrix(a, &tmat); // cvCopy( a, &tmat );
01421         else
01422                         LinearAlgebra::Transpose(a, &tmat); // cvT( a, &tmat );
01423         a = &tmat;
01424     }
01425 
01426     if( temp_u )
01427     {
01428                 ustub.rows = u_cols;
01429                 ustub.columns = u_rows;
01430                 ustub.data = (float *)(buffer + u_buf_offset * pix_size);
01431         u = &ustub;
01432     }
01433 
01434     if( !tw )
01435         tw = buffer + (n + m)*pix_size;
01436 
01437     
01438         
01439         icvSVD_32f( a->data, a->columns, a->rows, a->columns,
01440                (float*)tw, u->data, u->columns, u_cols,
01441                v->data, v->columns, (float*)buffer );
01442 
01443 
01444     if( (void *) tw != (void *) w->data )
01445     {
01446         int shift = w->columns != 1;
01447                 ImageProcessor::Zero(w); // cvSetZero( w );
01448         
01449                 for( int i = 0; i < n; i++ )
01450                 ((float*)(((unsigned char *) w->data) + i*(w->columns*sizeof(float))))[i*shift] = ((float*)tw)[i];
01451     }
01452 
01453     if( uarr )
01454     {
01455         if( !(flags & CV_SVD_U_T))
01456             LinearAlgebra::Transpose(u, uarr); // cvT( u, uarr );
01457         else if( temp_u )
01458             ImageProcessor::CopyMatrix(u, uarr); // cvCopy( u, uarr );
01459     }
01460 
01461     if( varr )
01462     {
01463         if( !(flags & CV_SVD_V_T))
01464             LinearAlgebra::Transpose(v, varr); // cvT( v, varr );
01465     }
01466 
01467     if( buffer )
01468         free( buffer );
01469 }
01470 
01471 void
01472 cvSVD( const CDoubleMatrix* aarr, CDoubleMatrix* warr, CDoubleMatrix* uarr, CDoubleMatrix* varr, int flags )
01473 {
01474         typedef unsigned char uchar;
01475 
01476     uchar* buffer = 0;
01477     //int local_alloc = 0;
01478 
01479     CDoubleMatrix tmat;
01480         CDoubleMatrix ustub, vstub;
01481 
01482         const CDoubleMatrix *a = aarr;
01483         CDoubleMatrix *w = warr;
01484 
01485     uchar* tw = 0;
01486     int a_buf_offset = 0, u_buf_offset = 0, buf_size, pix_size;
01487     int temp_u = 0, /* temporary storage for U is needed */
01488         t_svd; /* special case: a->rows < a->columns */
01489     int m, n;
01490     int w_rows, w_cols;
01491     int u_rows = 0, u_cols = 0;
01492     int w_is_mat = 0;
01493 
01494     if( a->rows >= a->columns )
01495     {
01496         m = a->rows;
01497         n = a->columns;
01498         w_rows = w->rows;
01499         w_cols = w->columns;
01500         t_svd = 0;
01501     }
01502     else
01503     {
01504         CDoubleMatrix* t;
01505         CV_SWAP( uarr, varr, t );
01506 
01507         flags = (flags & CV_SVD_U_T ? CV_SVD_V_T : 0)|
01508                 (flags & CV_SVD_V_T ? CV_SVD_U_T : 0);
01509         m = a->columns;
01510         n = a->rows;
01511         w_rows = w->columns;
01512         w_cols = w->rows;
01513         t_svd = 1;
01514     }
01515 
01516         CDoubleMatrix *u = uarr;
01517         CDoubleMatrix *v = varr;
01518 
01519     w_is_mat = w_cols > 1 && w_rows > 1;
01520         if (!w_is_mat && w_cols + w_rows - 1 == n)
01521                 tw = (uchar*) w->data;
01522 
01523     if( u )
01524     {
01525         if( !(flags & CV_SVD_U_T) )
01526         {
01527             u_rows = u->rows;
01528             u_cols = u->columns;
01529         }
01530         else
01531         {
01532             u_rows = u->columns;
01533             u_cols = u->rows;
01534         }
01535 
01536         if( u_rows != m || (u_cols != m && u_cols != n))
01537             !t_svd ? printf( "U matrix has unappropriate size" ) : printf( "V matrix has unappropriate size" );
01538             
01539         temp_u = (u_rows != u_cols && !(flags & CV_SVD_U_T)) || u->data == a->data;
01540 
01541         if( w_is_mat && u_cols != w_rows )
01542             !t_svd ? printf( "U and W have incompatible sizes" ) : printf( "V and W have incompatible sizes" );
01543     }
01544     else
01545     {
01546         u = &ustub;
01547                 u->rows = 0;
01548                 u->columns = 0;
01549         u->data = 0;
01550     }
01551 
01552     if( v )
01553     {
01554         int v_rows, v_cols;
01555 
01556         if( !(flags & CV_SVD_V_T) )
01557         {
01558             v_rows = v->rows;
01559             v_cols = v->columns;
01560         }
01561         else
01562         {
01563             v_rows = v->columns;
01564             v_cols = v->rows;
01565         }
01566 
01567         if( v_rows != n || v_cols != n )
01568             t_svd ? printf( "U matrix has unappropriate size" ) : printf( "V matrix has unappropriate size" );
01569 
01570         if( w_is_mat && w_cols != v_cols )
01571             t_svd ? printf( "U and W have incompatible sizes" ) : printf( "V and W have incompatible sizes" );
01572     }
01573     else
01574     {
01575         v = &vstub;
01576                 v->rows = 0;
01577                 v->columns = 0;
01578         v->data = 0;
01579     }
01580 
01581     pix_size = sizeof(double);
01582     buf_size = n*2 + m;
01583 
01584     if( !(flags & CV_SVD_MODIFY_A) )
01585     {
01586         a_buf_offset = buf_size;
01587         buf_size += a->rows*a->columns;
01588     }
01589 
01590     if( temp_u )
01591     {
01592         u_buf_offset = buf_size;
01593         buf_size += u->rows*u->columns;
01594     }
01595 
01596     buf_size *= pix_size;
01597 
01598     buffer = (uchar*)malloc( buf_size );
01599     
01600     if( !(flags & CV_SVD_MODIFY_A) )
01601     {
01602                 tmat.rows = m;
01603                 tmat.columns = n;
01604                 tmat.data = (double *)(buffer + a_buf_offset * pix_size);
01605 
01606         if( !t_svd )
01607                         ImageProcessor::CopyMatrix(a, &tmat); // cvCopy( a, &tmat );
01608         else
01609                         LinearAlgebra::Transpose(a, &tmat); // cvT( a, &tmat );
01610         a = &tmat;
01611     }
01612 
01613     if( temp_u )
01614     {
01615                 ustub.rows = u_cols;
01616                 ustub.columns = u_rows;
01617                 ustub.data = (double *)(buffer + u_buf_offset * pix_size);
01618         u = &ustub;
01619     }
01620 
01621     if( !tw )
01622         tw = buffer + (n + m)*pix_size;
01623 
01624     
01625         
01626         icvSVD_64f( a->data, a->columns, a->rows, a->columns,
01627                (double*)tw, u->data, u->columns, u_cols,
01628                v->data, v->columns, (double*)buffer );
01629 
01630 
01631     if( (void *) tw != (void *) w->data )
01632     {
01633         int shift = w->columns != 1;
01634                 ImageProcessor::Zero(w); // cvSetZero( w );
01635         
01636                 for( int i = 0; i < n; i++ )
01637                 ((double*)(((unsigned char *) w->data) + i*(w->columns*sizeof(double))))[i*shift] = ((double*)tw)[i];
01638     }
01639 
01640     if( uarr )
01641     {
01642         if( !(flags & CV_SVD_U_T))
01643             LinearAlgebra::Transpose(u, uarr); // cvT( u, uarr );
01644         else if( temp_u )
01645             ImageProcessor::CopyMatrix(u, uarr); // cvCopy( u, uarr );
01646     }
01647 
01648     if( varr )
01649     {
01650         if( !(flags & CV_SVD_V_T))
01651             LinearAlgebra::Transpose(v, varr); // cvT( v, varr );
01652     }
01653 
01654     if( buffer )
01655         free( buffer );
01656 }
01657 } // End of unnamed namespace
01658 
01659 
01660 void LinearAlgebra::SVD(const CFloatMatrix *A, CFloatMatrix *W, CFloatMatrix *U, CFloatMatrix *V, bool bAllowModifyA, bool bReturnUTransposed, bool bReturnVTransposed)
01661 {
01662         const int columns = A->columns;
01663         const int rows = A->rows;
01664 
01665         if (W->columns != columns || W->rows != rows)
01666         {
01667                 printf("error: W should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, rows);
01668                 return;
01669         }
01670 
01671         if (U && (U->columns != rows || U->rows != rows))
01672         {
01673                 printf("error: U should have %i columns and %i rows for LinearAlgebra::SVD\n", rows, rows);
01674                 return;
01675         }
01676 
01677         if (V && (V->columns != columns || V->rows != columns))
01678         {
01679                 printf("error: V should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, columns);
01680                 return;
01681         }
01682 
01683         int flags = 0;
01684 
01685         if (bAllowModifyA)
01686                 flags |= CV_SVD_MODIFY_A;
01687 
01688         if (bReturnUTransposed)
01689                 flags |= CV_SVD_U_T;
01690 
01691         if (bReturnVTransposed)
01692                 flags |= CV_SVD_V_T;
01693 
01694         cvSVD(A, W, U, V, flags);
01695 }
01696 
01697 void LinearAlgebra::SVD(const CDoubleMatrix *A, CDoubleMatrix *W, CDoubleMatrix *U, CDoubleMatrix *V, bool bAllowModifyA, bool bReturnUTransposed, bool bReturnVTransposed)
01698 {
01699         const int columns = A->columns;
01700         const int rows = A->rows;
01701 
01702         if (W->columns != columns || W->rows != rows)
01703         {
01704                 printf("error: W should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, rows);
01705                 return;
01706         }
01707 
01708         if (U && (U->columns != rows || U->rows != rows))
01709         {
01710                 printf("error: U should have %i columns and %i rows for LinearAlgebra::SVD\n", rows, rows);
01711                 return;
01712         }
01713 
01714         if (V && (V->columns != columns || V->rows != columns))
01715         {
01716                 printf("error: V should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, columns);
01717                 return;
01718         }
01719 
01720         int flags = 0;
01721 
01722         if (bAllowModifyA)
01723                 flags |= CV_SVD_MODIFY_A;
01724 
01725         if (bReturnUTransposed)
01726                 flags |= CV_SVD_U_T;
01727 
01728         if (bReturnVTransposed)
01729                 flags |= CV_SVD_V_T;
01730 
01731         cvSVD(A, W, U, V, flags);
01732 }


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:58