LCOV - code coverage report
Current view: directory - alg - thinplatespline.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 217 111 51.2 %
Date: 2012-04-28 Functions: 12 8 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: thinplatespline.cpp 22879 2011-08-07 01:00:45Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Warp API
       5                 :  * Purpose:  Implemenentation of 2D Thin Plate Spline transformer. 
       6                 :  * Author:   VIZRT Development Team.
       7                 :  *
       8                 :  * This code was provided by Gilad Ronnen (gro at visrt dot com) with
       9                 :  * permission to reuse under the following license.
      10                 :  * 
      11                 :  ******************************************************************************
      12                 :  * Copyright (c) 2004, VIZRT Inc.
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  *
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  *
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  ****************************************************************************/
      32                 : 
      33                 : #ifdef HAVE_ARMADILLO
      34                 : /* Include before #define A(r,c) because armadillo uses A in its include files */
      35                 : #include "armadillo"
      36                 : #endif
      37                 : 
      38                 : #include "thinplatespline.h"
      39                 : 
      40                 : #ifdef HAVE_FLOAT_H
      41                 : #  include <float.h>
      42                 : #elif defined(HAVE_VALUES_H)
      43                 : #  include <values.h>
      44                 : #endif
      45                 : 
      46                 : #ifndef FLT_MAX
      47                 : #  define FLT_MAX 1e+37
      48                 : #  define FLT_MIN 1e-37
      49                 : #endif
      50                 : 
      51                 : VizGeorefSpline2D* viz_xy2llz;
      52                 : VizGeorefSpline2D* viz_llz2xy;
      53                 : 
      54                 : /////////////////////////////////////////////////////////////////////////////////////
      55                 : //// vizGeorefSpline2D
      56                 : /////////////////////////////////////////////////////////////////////////////////////
      57                 : 
      58                 : #define A(r,c) _AA[ _nof_eqs * (r) + (c) ]
      59                 : #define Ainv(r,c) _Ainv[ _nof_eqs * (r) + (c) ]
      60                 : 
      61                 : 
      62                 : #define VIZ_GEOREF_SPLINE_DEBUG 0
      63                 : 
      64                 : static int matrixInvert( int N, double input[], double output[] );
      65                 : 
      66              40 : void VizGeorefSpline2D::grow_points()
      67                 : 
      68                 : {
      69              40 :     int new_max = _max_nof_points*2 + 2 + 3;
      70                 :     int i;
      71                 :     
      72              40 :     if( _max_nof_points == 0 )
      73                 :     {
      74              20 :         x = (double *) VSIMalloc( sizeof(double) * new_max );
      75              20 :         y = (double *) VSIMalloc( sizeof(double) * new_max );
      76              20 :         u = (double *) VSIMalloc( sizeof(double) * new_max );
      77              20 :         unused = (int *) VSIMalloc( sizeof(int) * new_max );
      78              20 :         index = (int *) VSIMalloc( sizeof(int) * new_max );
      79              60 :         for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
      80                 :         {
      81              40 :             rhs[i] = (double *) VSICalloc( sizeof(double), new_max );
      82              40 :             coef[i] = (double *) VSICalloc( sizeof(double), new_max );
      83                 :         }
      84                 :     }
      85                 :     else
      86                 :     {
      87              20 :         x = (double *) VSIRealloc( x, sizeof(double) * new_max );
      88              20 :         y = (double *) VSIRealloc( y, sizeof(double) * new_max );
      89              20 :         u = (double *) VSIRealloc( u, sizeof(double) * new_max );
      90              20 :         unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
      91              20 :         index = (int *) VSIRealloc( index, sizeof(int) * new_max );
      92              60 :         for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
      93                 :         {
      94              40 :             rhs[i] = (double *) 
      95              40 :                 VSIRealloc( rhs[i], sizeof(double) * new_max );
      96              40 :             coef[i] = (double *) 
      97              40 :                 VSIRealloc( coef[i], sizeof(double) * new_max );
      98                 :         }
      99                 :     }
     100                 : 
     101              40 :     _max_nof_points = new_max - 3;
     102              40 : }
     103                 : 
     104              80 : int VizGeorefSpline2D::add_point( const double Px, const double Py, const double *Pvars )
     105                 : {
     106              80 :     type = VIZ_GEOREF_SPLINE_POINT_WAS_ADDED;
     107                 :     int i;
     108                 : 
     109              80 :     if( _nof_points == _max_nof_points )
     110              20 :         grow_points();
     111                 : 
     112              80 :     i = _nof_points;
     113                 :     //A new point is added
     114              80 :     x[i] = Px;
     115              80 :     y[i] = Py;
     116             240 :     for ( int j = 0; j < _nof_vars; j++ )
     117             160 :         rhs[j][i+3] = Pvars[j];
     118              80 :     _nof_points++;
     119              80 :     return 1;
     120                 : }
     121                 : 
     122               0 : bool VizGeorefSpline2D::change_point(int index, double Px, double Py, double* Pvars)
     123                 : {
     124               0 :     if ( index < _nof_points )
     125                 :     {
     126               0 :         int i = index;
     127               0 :         x[i] = Px;
     128               0 :         y[i] = Py;
     129               0 :         for ( int j = 0; j < _nof_vars; j++ )
     130               0 :             rhs[j][i+3] = Pvars[j];
     131                 :     }
     132                 : 
     133               0 :     return( true );
     134                 : }
     135                 : 
     136               0 : bool VizGeorefSpline2D::get_xy(int index, double& outX, double& outY)
     137                 : {
     138                 :     bool ok;
     139                 : 
     140               0 :     if ( index < _nof_points )
     141                 :     {
     142               0 :         ok = true;
     143               0 :         outX = x[index];
     144               0 :         outY = y[index];
     145                 :     }
     146                 :     else
     147                 :     {
     148               0 :         ok = false;
     149               0 :         outX = outY = 0.0f;
     150                 :     }
     151                 : 
     152               0 :     return(ok);
     153                 : }
     154                 : 
     155               0 : int VizGeorefSpline2D::delete_point(const double Px, const double Py )
     156                 : {
     157               0 :     for ( int i = 0; i < _nof_points; i++ )
     158                 :     {
     159               0 :         if ( ( fabs(Px - x[i]) <= _tx ) && ( fabs(Py - y[i]) <= _ty ) )
     160                 :         {
     161               0 :             for ( int j = i; j < _nof_points - 1; j++ )
     162                 :             {
     163               0 :                 x[j] = x[j+1];
     164               0 :                 y[j] = y[j+1];
     165               0 :                 for ( int k = 0; k < _nof_vars; k++ )
     166               0 :                     rhs[k][j+3] = rhs[k][j+3+1];
     167                 :             }
     168               0 :             _nof_points--;
     169               0 :             type = VIZ_GEOREF_SPLINE_POINT_WAS_DELETED;
     170               0 :             return(1);
     171                 :         }
     172                 :     }
     173               0 :     return(0);
     174                 : }
     175                 : 
     176              20 : int VizGeorefSpline2D::solve(void)
     177                 : {
     178                 :     int r, c, v;
     179                 :     int p;
     180                 :   
     181                 :     //  No points at all
     182              20 :     if ( _nof_points < 1 )
     183                 :     {
     184               0 :         type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
     185               0 :         return(0);
     186                 :     }
     187                 :   
     188                 :     // Only one point
     189              20 :     if ( _nof_points == 1 )
     190                 :     {
     191               0 :         type = VIZ_GEOREF_SPLINE_ONE_POINT;
     192               0 :         return(1);
     193                 :     }
     194                 :     // Just 2 points - it is necessarily 1D case
     195              20 :     if ( _nof_points == 2 )
     196                 :     {
     197               0 :         _dx = x[1] - x[0];
     198               0 :         _dy = y[1] - y[0];   
     199               0 :         double fact = 1.0 / ( _dx * _dx + _dy * _dy );
     200               0 :         _dx *= fact;
     201               0 :         _dy *= fact;
     202                 :     
     203               0 :         type = VIZ_GEOREF_SPLINE_TWO_POINTS;
     204               0 :         return(2);
     205                 :     }
     206                 :   
     207                 :     // More than 2 points - first we have to check if it is 1D or 2D case
     208                 :     
     209              20 :     double xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
     210                 :     double delx, dely;
     211                 :     double xx, yy;
     212              20 :     double sumx = 0.0f, sumy= 0.0f, sumx2 = 0.0f, sumy2 = 0.0f, sumxy = 0.0f;
     213                 :     double SSxx, SSyy, SSxy;
     214                 :   
     215             100 :     for ( p = 0; p < _nof_points; p++ )
     216                 :     {
     217              80 :         xx = x[p];
     218              80 :         yy = y[p];
     219                 :     
     220              80 :         xmax = MAX( xmax, xx );
     221              80 :         xmin = MIN( xmin, xx );
     222              80 :         ymax = MAX( ymax, yy );
     223              80 :         ymin = MIN( ymin, yy );
     224                 :     
     225              80 :         sumx  += xx;
     226              80 :         sumx2 += xx * xx;
     227              80 :         sumy  += yy;
     228              80 :         sumy2 += yy * yy;
     229              80 :         sumxy += xx * yy;
     230                 :     }
     231              20 :     delx = xmax - xmin;
     232              20 :     dely = ymax - ymin;
     233                 :   
     234              20 :     SSxx = sumx2 - sumx * sumx / _nof_points;
     235              20 :     SSyy = sumy2 - sumy * sumy / _nof_points;
     236              20 :     SSxy = sumxy - sumx * sumy / _nof_points;
     237                 :   
     238              20 :     if ( delx < 0.001 * dely || dely < 0.001 * delx || 
     239                 :          fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
     240                 :     {
     241                 :         int p1;
     242                 :     
     243               0 :         type = VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL;
     244                 :     
     245               0 :         _dx = _nof_points * sumx2 - sumx * sumx;
     246               0 :         _dy = _nof_points * sumy2 - sumy * sumy;
     247               0 :         double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
     248               0 :         _dx *= fact;
     249               0 :         _dy *= fact;
     250                 :     
     251               0 :         for ( p = 0; p < _nof_points; p++ )
     252                 :         {
     253               0 :             double dxp = x[p] - x[0];
     254               0 :             double dyp = y[p] - y[0];
     255               0 :             u[p] = _dx * dxp + _dy * dyp;
     256               0 :             unused[p] = 1;
     257                 :         }
     258                 :     
     259               0 :         for ( p = 0; p < _nof_points; p++ )
     260                 :         {
     261               0 :             int min_index = -1;
     262               0 :             double min_u = 0;
     263               0 :             for ( p1 = 0; p1 < _nof_points; p1++ )
     264                 :             {
     265               0 :                 if ( unused[p1] )
     266                 :                 {
     267               0 :                     if ( min_index < 0 || u[p1] < min_u )
     268                 :                     {
     269               0 :                         min_index = p1;
     270               0 :                         min_u = u[p1];
     271                 :                     }
     272                 :                 }
     273                 :             }
     274               0 :             index[p] = min_index;
     275               0 :             unused[min_index] = 0;
     276                 :         }
     277                 :     
     278               0 :         return(3);
     279                 :     }
     280                 :   
     281              20 :     type = VIZ_GEOREF_SPLINE_FULL;
     282                 :     // Make the necessary memory allocations
     283              20 :     if ( _AA )
     284               0 :         CPLFree(_AA);
     285              20 :     if ( _Ainv )
     286               0 :         CPLFree(_Ainv);
     287                 :   
     288              20 :     _nof_eqs = _nof_points + 3;
     289                 :   
     290              20 :     _AA = ( double * )CPLCalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
     291              20 :     _Ainv = ( double * )CPLCalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
     292                 :   
     293                 :     // Calc the values of the matrix A
     294              80 :     for ( r = 0; r < 3; r++ )
     295             240 :         for ( c = 0; c < 3; c++ )
     296             180 :             A(r,c) = 0.0;
     297                 :     
     298             100 :     for ( c = 0; c < _nof_points; c++ )
     299                 :     {
     300              80 :         A(0,c+3) = 1.0;
     301              80 :         A(1,c+3) = x[c];
     302              80 :         A(2,c+3) = y[c];
     303                 :       
     304              80 :         A(c+3,0) = 1.0;
     305              80 :         A(c+3,1) = x[c];
     306              80 :         A(c+3,2) = y[c];
     307                 :     }
     308                 :     
     309             100 :     for ( r = 0; r < _nof_points; r++ )
     310             280 :         for ( c = r; c < _nof_points; c++ )
     311                 :         {
     312             200 :             A(r+3,c+3) = base_func( x[r], y[r], x[c], y[c] );
     313             200 :             if ( r != c )
     314             120 :                 A(c+3,r+3 ) = A(r+3,c+3);
     315                 :         }
     316                 :       
     317                 : #if VIZ_GEOREF_SPLINE_DEBUG
     318                 :       
     319                 :     for ( r = 0; r < _nof_eqs; r++ )
     320                 :     {
     321                 :         for ( c = 0; c < _nof_eqs; c++ )
     322                 :             fprintf(stderr, "%f", A(r,c));
     323                 :         fprintf(stderr, "\n");
     324                 :     }
     325                 :       
     326                 : #endif
     327                 :       
     328                 :     // Invert the matrix
     329              20 :     int status = matrixInvert( _nof_eqs, _AA, _Ainv );
     330                 :       
     331              20 :     if ( !status )
     332                 :     {
     333               0 :         fprintf(stderr, " There is a problem to invert the interpolation matrix\n");
     334               0 :         return 0;
     335                 :     }
     336                 :       
     337                 :     // calc the coefs
     338              60 :     for ( v = 0; v < _nof_vars; v++ )
     339             320 :         for ( r = 0; r < _nof_eqs; r++ )
     340                 :         {
     341             280 :             coef[v][r] = 0.0;
     342            2240 :             for ( c = 0; c < _nof_eqs; c++ )
     343            1960 :                 coef[v][r] += Ainv(r,c) * rhs[v][c];
     344                 :         }
     345                 :         
     346              20 :     return(4);
     347                 : }
     348                 : 
     349            5124 : int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars )
     350                 : {
     351                 :   int v, r;
     352                 :   double tmp, Pu;
     353                 :   double fact;
     354            5124 :   int leftP=0, rightP=0, found = 0;
     355                 :   
     356            5124 :   switch ( type )
     357                 :   {
     358                 :   case VIZ_GEOREF_SPLINE_ZERO_POINTS :
     359               0 :     for ( v = 0; v < _nof_vars; v++ )
     360               0 :       vars[v] = 0.0;
     361               0 :     break;
     362                 :   case VIZ_GEOREF_SPLINE_ONE_POINT :
     363               0 :     for ( v = 0; v < _nof_vars; v++ )
     364               0 :       vars[v] = rhs[v][3];
     365               0 :     break;
     366                 :   case VIZ_GEOREF_SPLINE_TWO_POINTS :
     367               0 :     fact = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
     368               0 :     for ( v = 0; v < _nof_vars; v++ )
     369               0 :       vars[v] = ( 1 - fact ) * rhs[v][3] + fact * rhs[v][4];
     370               0 :     break;
     371                 :   case VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL :
     372               0 :     Pu = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
     373               0 :     if ( Pu <= u[index[0]] )
     374                 :     {
     375               0 :       leftP = index[0];
     376               0 :       rightP = index[1];
     377                 :     }
     378               0 :     else if ( Pu >= u[index[_nof_points-1]] )
     379                 :     {
     380               0 :       leftP = index[_nof_points-2];
     381               0 :       rightP = index[_nof_points-1];
     382                 :     }
     383                 :     else
     384                 :     {
     385               0 :       for ( r = 1; !found && r < _nof_points; r++ )
     386                 :       {
     387               0 :         leftP = index[r-1];
     388               0 :         rightP = index[r];          
     389               0 :         if ( Pu >= u[leftP] && Pu <= u[rightP] )
     390               0 :           found = 1;
     391                 :       }
     392                 :     }
     393                 :     
     394               0 :     fact = ( Pu - u[leftP] ) / ( u[rightP] - u[leftP] );
     395               0 :     for ( v = 0; v < _nof_vars; v++ )
     396               0 :       vars[v] = ( 1.0 - fact ) * rhs[v][leftP+3] +
     397               0 :       fact * rhs[v][rightP+3];
     398               0 :     break;
     399                 :   case VIZ_GEOREF_SPLINE_FULL :
     400           15372 :     for ( v = 0; v < _nof_vars; v++ )
     401           10248 :       vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
     402                 :     
     403           25620 :     for ( r = 0; r < _nof_points; r++ )
     404                 :     {
     405           20496 :       tmp = base_func( Px, Py, x[r], y[r] );
     406           61488 :       for ( v= 0; v < _nof_vars; v++ )
     407           40992 :         vars[v] += coef[v][r+3] * tmp;
     408                 :     }
     409            5124 :     break;
     410                 :   case VIZ_GEOREF_SPLINE_POINT_WAS_ADDED :
     411               0 :     fprintf(stderr, " A point was added after the last solve\n");
     412               0 :     fprintf(stderr, " NO interpolation - return values are zero\n");
     413               0 :     for ( v = 0; v < _nof_vars; v++ )
     414               0 :       vars[v] = 0.0;
     415               0 :     return(0);
     416                 :     break;
     417                 :   case VIZ_GEOREF_SPLINE_POINT_WAS_DELETED :
     418               0 :     fprintf(stderr, " A point was deleted after the last solve\n");
     419               0 :     fprintf(stderr, " NO interpolation - return values are zero\n");
     420               0 :     for ( v = 0; v < _nof_vars; v++ )
     421               0 :       vars[v] = 0.0;
     422               0 :     return(0);
     423                 :     break;
     424                 :   default :
     425               0 :     return(0);
     426                 :     break;
     427                 :   }
     428            5124 :   return(1);
     429                 : }
     430                 : 
     431           20696 : double VizGeorefSpline2D::base_func( const double x1, const double y1,
     432                 :               const double x2, const double y2 )
     433                 : {
     434           20696 :   if ( ( x1 == x2 ) && (y1 == y2 ) )
     435             198 :     return 0.0;
     436                 :   
     437           20498 :   double dist  = ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 );
     438                 :   
     439           20498 :   return dist * log( dist );  
     440                 : }
     441                 : 
     442                 : #ifdef HAVE_ARMADILLO
     443                 : 
     444              20 : static int matrixInvert( int N, double input[], double output[] )
     445                 : {
     446                 :     try
     447                 :     {
     448              20 :         arma::mat matInput(input,N,N,false);
     449              20 :         const arma::mat& matInv = arma::inv(matInput);
     450                 :         int row, col;
     451             160 :         for(row = 0; row < N; row++)
     452            1120 :             for(col = 0; col < N; col++)
     453            1960 :                 output[row * N + col] = matInv.at(row, col);
     454              20 :         return true;
     455                 :         //arma::mat matInv(output,N,N,false);
     456                 :         //return arma::inv(matInv, matInput);
     457                 :     }
     458               0 :     catch(...)
     459                 :     {
     460               0 :         fprintf(stderr, "matrixInvert(): error occured.\n");
     461               0 :         return false;
     462                 :     }
     463            4029 : }
     464                 : 
     465                 : #else
     466                 : 
     467                 : static int matrixInvert( int N, double input[], double output[] )
     468                 : {
     469                 :     // Receives an array of dimension NxN as input.  This is passed as a one-
     470                 :     // dimensional array of N-squared size.  It produces the inverse of the
     471                 :     // input matrix, returned as output, also of size N-squared.  The Gauss-
     472                 :     // Jordan Elimination method is used.  (Adapted from a BASIC routine in
     473                 :     // "Basic Scientific Subroutines Vol. 1", courtesy of Scott Edwards.)
     474                 :   
     475                 :     // Array elements 0...N-1 are for the first row, N...2N-1 are for the
     476                 :     // second row, etc.
     477                 :   
     478                 :     // We need to have a temporary array of size N x 2N.  We'll refer to the
     479                 :     // "left" and "right" halves of this array.
     480                 :   
     481                 :     int row, col;
     482                 :   
     483                 : #if 0
     484                 :     fprintf(stderr, "Matrix Inversion input matrix (N=%d)\n", N);
     485                 :     for ( row=0; row<N; row++ )
     486                 :     {
     487                 :         for ( col=0; col<N; col++ )
     488                 :         {
     489                 :             fprintf(stderr, "%5.2f ", input[row*N + col ]  );
     490                 :         }
     491                 :         fprintf(stderr, "\n");
     492                 :     }
     493                 : #endif
     494                 :   
     495                 :     int tempSize = 2 * N * N;
     496                 :     double* temp = (double*) new double[ tempSize ];
     497                 :     double ftemp;
     498                 :   
     499                 :     if (temp == 0) {
     500                 :     
     501                 :         fprintf(stderr, "matrixInvert(): ERROR - memory allocation failed.\n");
     502                 :         return false;
     503                 :     }
     504                 :   
     505                 :     // First create a double-width matrix with the input array on the left
     506                 :     // and the identity matrix on the right.
     507                 :   
     508                 :     for ( row=0; row<N; row++ )
     509                 :     {
     510                 :         for ( col=0; col<N; col++ )
     511                 :         {
     512                 :             // Our index into the temp array is X2 because it's twice as wide
     513                 :             // as the input matrix.
     514                 :       
     515                 :             temp[ 2*row*N + col ] = input[ row*N+col ]; // left = input matrix
     516                 :             temp[ 2*row*N + col + N ] = 0.0f;     // right = 0
     517                 :         }
     518                 :         temp[ 2*row*N + row + N ] = 1.0f;   // 1 on the diagonal of RHS
     519                 :     }
     520                 :   
     521                 :     // Now perform row-oriented operations to convert the left hand side
     522                 :     // of temp to the identity matrix.  The inverse of input will then be
     523                 :     // on the right.
     524                 :   
     525                 :     int max;
     526                 :     int k=0;
     527                 :     for (k = 0; k < N; k++)
     528                 :     {
     529                 :         if (k+1 < N) // if not on the last row
     530                 :         {              
     531                 :             max = k;
     532                 :             for (row = k+1; row < N; row++) // find the maximum element
     533                 :             {  
     534                 :                 if (fabs( temp[row*2*N + k] ) > fabs( temp[max*2*N + k] ))
     535                 :                 {
     536                 :                     max = row;
     537                 :                 }
     538                 :             }
     539                 :       
     540                 :             if (max != k) // swap all the elements in the two rows
     541                 :             {        
     542                 :                 for (col=k; col<2*N; col++)
     543                 :                 {
     544                 :                     ftemp = temp[k*2*N + col];
     545                 :                     temp[k*2*N + col] = temp[max*2*N + col];
     546                 :                     temp[max*2*N + col] = ftemp;
     547                 :                 }
     548                 :             }
     549                 :         }
     550                 :     
     551                 :         ftemp = temp[ k*2*N + k ];
     552                 :         if ( ftemp == 0.0f ) // matrix cannot be inverted
     553                 :         {
     554                 :             delete[] temp;
     555                 :             return false;
     556                 :         }
     557                 :     
     558                 :         for ( col=k; col<2*N; col++ )
     559                 :         {
     560                 :             temp[ k*2*N + col ] /= ftemp;
     561                 :         }
     562                 :     
     563                 :         int i2 = k*2*N ;
     564                 :         for ( row=0; row<N; row++ )
     565                 :         {
     566                 :             if ( row != k )
     567                 :             {
     568                 :                 int i1 = row*2*N;
     569                 :                 ftemp = temp[ i1 + k ];
     570                 :                 for ( col=k; col<2*N; col++ ) 
     571                 :                 {
     572                 :                     temp[ i1 + col ] -= ftemp * temp[ i2 + col ];
     573                 :                 }
     574                 :             }
     575                 :         }
     576                 :     }
     577                 :   
     578                 :     // Retrieve inverse from the right side of temp
     579                 :   
     580                 :     for (row = 0; row < N; row++)
     581                 :     {
     582                 :         for (col = 0; col < N; col++)
     583                 :         {
     584                 :             output[row*N + col] = temp[row*2*N + col + N ];
     585                 :         }
     586                 :     }
     587                 :   
     588                 : #if 0
     589                 :     fprintf(stderr, "Matrix Inversion result matrix:\n");
     590                 :     for ( row=0; row<N; row++ )
     591                 :     {
     592                 :         for ( col=0; col<N; col++ )
     593                 :         {
     594                 :             fprintf(stderr, "%5.2f ", output[row*N + col ]  );
     595                 :         }
     596                 :         fprintf(stderr, "\n");
     597                 :     }
     598                 : #endif
     599                 :   
     600                 :     delete [] temp;       // free memory
     601                 :     return true;
     602                 : }
     603                 : #endif

Generated by: LCOV version 1.7