LCOV - code coverage report
Current view: top level - lib_dec - ivas_svd_dec.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 266 277 96.0 %
Date: 2025-05-23 08:37:30 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include "prot.h"
      36             : #include "ivas_prot.h"
      37             : #include "ivas_stat_dec.h"
      38             : #include "ivas_cnst.h"
      39             : #include <math.h>
      40             : #ifdef DEBUGGING
      41             : #include "debug.h"
      42             : #endif
      43             : #include "wmc_auto.h"
      44             : 
      45             : 
      46             : /*-----------------------------------------------------------------------*
      47             :  * Local constants
      48             :  *-----------------------------------------------------------------------*/
      49             : 
      50             : /* The SVD is sensitive to changes to the following constants, so please be careful when trying to tune things   */
      51             : #define SVD_MINIMUM_VALUE        1e-32f   /* minimum value                                                   */
      52             : #define CONVERGENCE_FACTOR       1.0e-04f /* factor for SVD convergence                                      */
      53             : #define SVD_MAX_NUM_ITERATION    75       /* maximum number of interations before exiting the SVD            */
      54             : #define SVD_ZERO_FLUSH_THRESHOLD 1.0e-20f
      55             : 
      56             : 
      57             : /*-----------------------------------------------------------------------*
      58             :  * Local function prototypes
      59             :  *-----------------------------------------------------------------------*/
      60             : 
      61             : static float GivensRotation( const float x, const float z );
      62             : 
      63             : static void biDiagonalReductionLeft( float singularVectors[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *sig_x, float *g );
      64             : 
      65             : static void biDiagonalReductionRight( float singularVectors[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *sig_x, float *g );
      66             : 
      67             : static void singularVectorsAccumulationLeft( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC );
      68             : 
      69             : static void singularVectorsAccumulationRight( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularVectors_Right[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsC );
      70             : 
      71             : static void HouseholderReduction( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], float singularVectors_Right[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, float *eps_x );
      72             : 
      73             : static int16_t BidagonalDiagonalisation( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], float singularVectors_Right[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const float eps_x );
      74             : 
      75             : static void ApplyQRTransform( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], float singularVectors_Right[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t startIndex, const int16_t currentIndex, const int16_t nChannelsL, const int16_t nChannelsC );
      76             : 
      77             : static void ApplyRotation( float singularVector[][MAX_OUTPUT_CHANNELS], const float c, const float s, float x11, float x12, float *f, float *g, const int16_t currentIndex1, const int16_t currentIndex2, const int16_t nChannels );
      78             : 
      79             : static float maxWithSign( const float a );
      80             : 
      81             : static void flushToZeroArray( float arr[MAX_OUTPUT_CHANNELS], const int16_t length );
      82             : 
      83             : static void flushToZeroMat( float mat[][MAX_OUTPUT_CHANNELS], const int16_t m, const int16_t n );
      84             : 
      85             : 
      86             : /*-------------------------------------------------------------------------
      87             :  * mat2svdMat()
      88             :  *
      89             :  * external matrix format to internal
      90             :  *-------------------------------------------------------------------------*/
      91             : 
      92     3053268 : void mat2svdMat(
      93             :     const float *mat,                                       /* i  : matrix as column ordered vector */
      94             :     float svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o  : matrix as two-dimensional arry  */
      95             :     const int16_t nRows,                                    /* i  : number of rows of the matrix    */
      96             :     const int16_t mCols,                                    /* i  : number of columns of the matrix */
      97             :     const int16_t transpose                                 /* i  : flag indication transposition   */
      98             : )
      99             : {
     100             :     int16_t i, j;
     101             : 
     102     3053268 :     if ( transpose )
     103             :     {
     104     2492223 :         for ( i = 0; i < mCols; i++ )
     105             :         {
     106     6287691 :             for ( j = 0; j < nRows; j++ )
     107             :             {
     108     4204764 :                 svdMat[i][j] = mat[j + nRows * i];
     109             :             }
     110             : 
     111     2082927 :             set_zero( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - nRows );
     112             :         }
     113             : 
     114     4875105 :         for ( ; i < MAX_OUTPUT_CHANNELS; i++ )
     115             :         {
     116     4465809 :             set_zero( svdMat[i], MAX_OUTPUT_CHANNELS );
     117             :         }
     118             :     }
     119             :     else
     120             :     {
     121    11180925 :         for ( i = 0; i < nRows; i++ )
     122             :         {
     123    42640728 :             for ( j = 0; j < mCols; j++ )
     124             :             {
     125    34103775 :                 svdMat[i][j] = mat[i + nRows * j];
     126             :             }
     127             : 
     128     8536953 :             set_zero( &svdMat[i][mCols], MAX_OUTPUT_CHANNELS - mCols );
     129             :         }
     130             : 
     131    36410571 :         for ( ; i < MAX_OUTPUT_CHANNELS; i++ )
     132             :         {
     133    33766599 :             set_zero( svdMat[i], MAX_OUTPUT_CHANNELS );
     134             :         }
     135             :     }
     136             : 
     137     3053268 :     return;
     138             : }
     139             : 
     140             : 
     141             : /*---------------------------------------------------------------------*
     142             :  * svdMat2mat()
     143             :  *
     144             :  * transfer a matrix from a two dimensional array  to a column wise ordered vector
     145             :  *---------------------------------------------------------------------*/
     146             : 
     147     3871212 : void svdMat2mat(
     148             :     float svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* i  : matrix as two-dimensional arry  */
     149             :     float *mat,                                             /* o  : matrix as column ordered vector */
     150             :     const int16_t nRows,                                    /* i  : number of rows of the matrix    */
     151             :     const int16_t mCols                                     /* i  : number of columns of the matrix */
     152             : )
     153             : {
     154             :     int16_t i, j;
     155             : 
     156    14884245 :     for ( i = 0; i < nRows; i++ )
     157             :     {
     158             : 
     159             : 
     160    43594035 :         for ( j = 0; j < mCols; j++ )
     161             :         {
     162    32581002 :             mat[i + nRows * j] = svdMat[i][j];
     163             :         }
     164             :     }
     165             : 
     166     3871212 :     return;
     167             : }
     168             : 
     169             : 
     170             : /*-------------------------------------------------------------------------
     171             :  * svd()
     172             :  *
     173             :  * perform a singular value decomposition X=USV of a matrix X
     174             :  *-------------------------------------------------------------------------*/
     175             : 
     176             : /*! r: error or success */
     177     3053268 : int16_t svd(
     178             :     float InputMatrix[][MAX_OUTPUT_CHANNELS],           /* i  : matrix to be decomposed (M)                      */
     179             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],  /* o  : left singular vectors (U)                        */
     180             :     float singularValues[MAX_OUTPUT_CHANNELS],          /* o  : singular values vector (S)                       */
     181             :     float singularVectors_Right[][MAX_OUTPUT_CHANNELS], /* o  : right singular vectors (V)                       */
     182             :     const int16_t nChannelsL,                           /* i  : number of rows in the matrix to be decomposed    */
     183             :     const int16_t nChannelsC                            /* i  : number of columns in the matrix to be decomposed */
     184             : )
     185             : {
     186             :     int16_t iCh, jCh;
     187             :     int16_t lengthSingularValues;
     188             :     int16_t errorMessage, condition;
     189     3053268 :     int16_t max_length = ( ( nChannelsL > nChannelsC ) ? nChannelsL : nChannelsC );
     190             :     float secDiag[MAX_OUTPUT_CHANNELS];
     191     3053268 :     float eps_x = 0.0f, temp;
     192             : 
     193     3053268 :     push_wmops( "svd" );
     194             : 
     195     3053268 :     set_zero( secDiag, MAX_OUTPUT_CHANNELS );
     196             : 
     197             :     /* Collecting Values */
     198    13673148 :     for ( iCh = 0; iCh < nChannelsL; iCh++ )
     199             :     {
     200    48928419 :         for ( jCh = 0; jCh < nChannelsC; jCh++ )
     201             :         {
     202    38308539 :             singularVectors_Left[iCh][jCh] = InputMatrix[iCh][jCh];
     203             :         }
     204             :     }
     205             : 
     206             :     /* Householder reduction */
     207     3053268 :     HouseholderReduction( singularVectors_Left, singularValues, singularVectors_Right, secDiag, nChannelsL, nChannelsC, &eps_x );
     208             : 
     209             :     /* Set extremely small values to zero if needed */
     210     3053268 :     flushToZeroArray( singularValues, max_length );
     211     3053268 :     flushToZeroMat( singularVectors_Left, nChannelsL, nChannelsL );
     212     3053268 :     flushToZeroMat( singularVectors_Right, nChannelsC, nChannelsC );
     213             : 
     214             :     /* BidagonalDiagonalisation */
     215     3053268 :     errorMessage = BidagonalDiagonalisation( singularVectors_Left, singularValues, singularVectors_Right, secDiag, nChannelsL, nChannelsC, eps_x );
     216             : 
     217             :     /* Sort the singular values descending order */
     218     3053268 :     lengthSingularValues = min( nChannelsL, nChannelsC );
     219             : 
     220             :     do
     221             :     {
     222     4157337 :         condition = 0;
     223    14081925 :         for ( iCh = 0; iCh < lengthSingularValues - 1; iCh++ )
     224             :         {
     225     9924588 :             if ( singularValues[iCh] < singularValues[iCh + 1] )
     226             :             {
     227     1386972 :                 condition = 1;
     228     1386972 :                 temp = singularValues[iCh];
     229     1386972 :                 singularValues[iCh] = singularValues[iCh + 1];
     230     1386972 :                 singularValues[iCh + 1] = temp;
     231             : 
     232     7674792 :                 for ( jCh = 0; jCh < nChannelsL; ++jCh )
     233             :                 {
     234     6287820 :                     temp = singularVectors_Left[jCh][iCh];
     235     6287820 :                     singularVectors_Left[jCh][iCh] = singularVectors_Left[jCh][iCh + 1];
     236     6287820 :                     singularVectors_Left[jCh][iCh + 1] = temp;
     237             :                 }
     238             : 
     239     7649367 :                 for ( jCh = 0; jCh < nChannelsC; ++jCh )
     240             :                 {
     241     6262395 :                     temp = singularVectors_Right[jCh][iCh];
     242     6262395 :                     singularVectors_Right[jCh][iCh] = singularVectors_Right[jCh][iCh + 1];
     243     6262395 :                     singularVectors_Right[jCh][iCh + 1] = temp;
     244             :                 }
     245             :             }
     246             :         }
     247     4157337 :     } while ( condition == 1 );
     248             : 
     249     3053268 :     pop_wmops();
     250     3053268 :     return ( errorMessage );
     251             : }
     252             : 
     253             : 
     254             : /*-----------------------------------------------------------------------*
     255             :  * Local functions
     256             :  *-----------------------------------------------------------------------*/
     257             : 
     258             : /*-------------------------------------------------------------------------
     259             :  * BidagonalDiagonalisation()
     260             :  *
     261             :  *
     262             :  *-------------------------------------------------------------------------*/
     263             : 
     264     3053268 : static int16_t BidagonalDiagonalisation(
     265             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],  /* i/o: left singular vectors (U)                        */
     266             :     float singularValues[MAX_OUTPUT_CHANNELS],          /* i/o: singular values vector (S)                       */
     267             :     float singularVectors_Right[][MAX_OUTPUT_CHANNELS], /* i/o: right singular vectors (V)                       */
     268             :     float secDiag[MAX_OUTPUT_CHANNELS],                 /* i/o:                                                  */
     269             :     const int16_t nChannelsL,                           /* i  : number of rows in the matrix to be decomposed    */
     270             :     const int16_t nChannelsC,                           /* i  : number of columns in the matrix to be decomposed */
     271             :     const float eps_x                                   /* i  :                                                  */
     272             : )
     273             : {
     274             :     int16_t kCh, nCh, iCh, jCh, split;
     275             :     float c, s, f1, f2;
     276     3053268 :     float g = 0.0f;
     277             :     int16_t convergence, iteration, found_split;
     278     3053268 :     int16_t error = 0;
     279             : 
     280    12412893 :     for ( iCh = nChannelsC - 1; iCh >= 0; iCh-- ) /* nChannelsC */
     281             :     {
     282     9359625 :         convergence = 0;
     283     9359625 :         iteration = 0;
     284     9359625 :         split = iCh - 1;
     285             : 
     286    24660354 :         while ( convergence == 0 )
     287             :         {
     288    15300729 :             iteration++;
     289    15300729 :             found_split = 1;
     290             : 
     291    29165064 :             for ( jCh = iCh; jCh >= 0; jCh-- )
     292             :             {
     293    29165064 :                 split = jCh - 1;
     294    29165064 :                 if ( fabsf( secDiag[jCh] ) <= CONVERGENCE_FACTOR * eps_x ) /* is secDiag[ch] vanishing compared to eps_x */
     295             :                 {
     296    15068259 :                     found_split = 0;
     297    15068259 :                     break;
     298             :                 }
     299    14096805 :                 if ( fabsf( singularValues[split] ) <= CONVERGENCE_FACTOR * eps_x ) /* is singularValues[split] vanishing compared to eps_x */
     300             :                 {
     301      232470 :                     break;
     302             :                 }
     303             :             }
     304             : 
     305    15300729 :             convergence = ( jCh == iCh ) ? 1 : 0;
     306             : 
     307    15300729 :             if ( found_split )
     308             :             {
     309      232470 :                 s = 1.0f;
     310      232470 :                 c = 0.0f;
     311             : 
     312      465072 :                 for ( kCh = jCh; kCh <= iCh; kCh++ )
     313             :                 {
     314      232644 :                     g = s * secDiag[kCh];
     315      232644 :                     secDiag[kCh] = c * secDiag[kCh];
     316      232644 :                     if ( fabsf( g ) <= CONVERGENCE_FACTOR * eps_x )
     317             :                     {
     318          42 :                         break;
     319             :                     }
     320             : 
     321      232602 :                     c = singularValues[kCh];
     322      232602 :                     singularValues[kCh] = GivensRotation( g, singularValues[kCh] );
     323      232602 :                     c = c / maxWithSign( singularValues[kCh] );
     324      232602 :                     s = -g / maxWithSign( singularValues[kCh] );
     325             : 
     326      232602 :                     ApplyRotation( singularVectors_Left, c, s, 0, 0, &f1, &f2, kCh, split, nChannelsL ); /* nChannelsL */
     327             :                 }
     328             :             }
     329             : 
     330    15300729 :             if ( convergence )
     331             :             {
     332     9359625 :                 singularValues[iCh] = (float) singularValues[iCh];
     333     9359625 :                 if ( singularValues[iCh] < 0.0f )
     334             :                 {
     335     1758519 :                     singularValues[iCh] = -singularValues[iCh];
     336     6426483 :                     for ( nCh = 0; nCh < nChannelsC; nCh++ ) /* nChannelsC */
     337             :                     {
     338     4667964 :                         singularVectors_Right[nCh][iCh] = -singularVectors_Right[nCh][iCh];
     339             :                     }
     340             :                 }
     341             :             }
     342             :             else
     343             :             {
     344     5941104 :                 if ( iteration >= SVD_MAX_NUM_ITERATION )
     345             :                 {
     346           0 :                     if ( singularValues[iCh] < 0.0f )
     347             :                     {
     348           0 :                         singularValues[iCh] = -singularValues[iCh];
     349             : 
     350           0 :                         for ( nCh = 0; nCh < nChannelsC; nCh++ ) /* nChannelsC */
     351             :                         {
     352           0 :                             singularVectors_Right[nCh][iCh] = -singularVectors_Right[nCh][iCh];
     353             :                         }
     354             :                     }
     355           0 :                     error = 1;
     356           0 :                     convergence = 1;
     357             :                 }
     358             :                 else
     359             :                 {
     360     5941104 :                     ApplyQRTransform( singularVectors_Left, singularValues, singularVectors_Right, secDiag, jCh, iCh, nChannelsL, nChannelsC ); /* nChannelsC */
     361             :                 }
     362             :             }
     363             :         }
     364             :     }
     365             : 
     366     3053268 :     return ( error );
     367             : }
     368             : 
     369             : 
     370             : /*-------------------------------------------------------------------------
     371             :  * ApplyQRTransform()
     372             :  *
     373             :  *
     374             :  *-------------------------------------------------------------------------*/
     375             : 
     376     5941104 : static void ApplyQRTransform(
     377             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],  /* i/o: left singular vectors (U)                        */
     378             :     float singularValues[MAX_OUTPUT_CHANNELS],          /* i/o: singular values vector (S)                       */
     379             :     float singularVectors_Right[][MAX_OUTPUT_CHANNELS], /* i/o: right singular vectors (V)                       */
     380             :     float secDiag[MAX_OUTPUT_CHANNELS],                 /* i/o: */
     381             :     const int16_t startIndex,                           /* i  : */
     382             :     const int16_t currentIndex,                         /* i  : */
     383             :     const int16_t nChannelsL,                           /* i  : number of rows in the matrix to be decomposed    */
     384             :     const int16_t nChannelsC                            /* i  : number of columns in the matrix to be decomposed */
     385             : )
     386             : {
     387             :     int16_t ch, split;
     388     5941104 :     float d = 0.0f, g = 0.0f, r = 0.0f, x_ii = 0.0f, x_split = 0.0f, x_kk = 0.0f, mu = 0.0f, aux = 0.0f;
     389     5941104 :     float c = 1.0f;
     390     5941104 :     float s = 1.0f;
     391             : 
     392     5941104 :     x_kk = singularValues[currentIndex];
     393     5941104 :     x_ii = singularValues[startIndex];
     394     5941104 :     split = currentIndex - 1;
     395             : 
     396     5941104 :     x_split = singularValues[split];
     397     5941104 :     g = secDiag[split];
     398     5941104 :     r = secDiag[currentIndex];
     399             : 
     400     5941104 :     d = ( x_split + x_kk ) * ( x_split - x_kk ) + ( g + r ) * ( g - r );
     401     5941104 :     d /= maxWithSign( ( r + r ) * x_split );
     402             : 
     403     5941104 :     g = GivensRotation( 1.0f, d );
     404     5941104 :     mu = x_split / maxWithSign( d + ( d >= 0.0f ? 1 : ( -1 ) ) * fabsf( g ) ) - r;
     405     5941104 :     d = ( ( x_ii + x_kk ) * ( x_ii - x_kk ) + r * mu ) / maxWithSign( x_ii );
     406             : 
     407             :     /*QR transformation*/
     408    19805439 :     for ( ch = startIndex; ch <= split; ch++ )
     409             :     {
     410    13864335 :         r = s * secDiag[ch + 1];
     411    13864335 :         g = c * secDiag[ch + 1];
     412             : 
     413    13864335 :         secDiag[ch] = GivensRotation( d, r );
     414    13864335 :         c = d / maxWithSign( secDiag[ch] );
     415    13864335 :         s = r / maxWithSign( secDiag[ch] );
     416             : 
     417    13864335 :         r = s * singularValues[ch + 1];
     418    13864335 :         x_split = c * singularValues[ch + 1];
     419    13864335 :         aux = g;
     420    13864335 :         ApplyRotation( singularVectors_Right, c, s, x_ii, aux, &d, &g, ch + 1, ch, nChannelsC );
     421             : 
     422    13864335 :         singularValues[ch] = GivensRotation( d, r );
     423    13864335 :         if ( fabsf( singularValues[ch] ) > CONVERGENCE_FACTOR * fabsf( singularValues[ch] ) )
     424             :         {
     425    13859523 :             aux = 1.0f / singularValues[ch];
     426    13859523 :             c = d * aux;
     427    13859523 :             s = r * aux;
     428             :         }
     429             : 
     430    13864335 :         ApplyRotation( singularVectors_Left, c, s, g, x_split, &d, &x_ii, ch + 1, ch, nChannelsL );
     431             :     }
     432             : 
     433     5941104 :     secDiag[startIndex] = 0.0f;
     434     5941104 :     secDiag[currentIndex] = d;
     435     5941104 :     singularValues[currentIndex] = x_ii;
     436             : 
     437     5941104 :     return;
     438             : }
     439             : 
     440             : 
     441             : /*-------------------------------------------------------------------------
     442             :  * ApplyRotation()
     443             :  *
     444             :  *
     445             :  *-------------------------------------------------------------------------*/
     446             : 
     447    27961272 : static void ApplyRotation(
     448             :     float singularVector[][MAX_OUTPUT_CHANNELS],
     449             :     const float c,
     450             :     const float s,
     451             :     float x11,
     452             :     float x12,
     453             :     float *d,
     454             :     float *g,
     455             :     const int16_t currentIndex1,
     456             :     const int16_t currentIndex2,
     457             :     const int16_t nChannels )
     458             : {
     459             :     int16_t ch;
     460             : 
     461    27961272 :     *d = c * x11 + s * x12;
     462    27961272 :     *g = c * x12 - s * x11;
     463             : 
     464   166497225 :     for ( ch = 0; ch < nChannels; ch++ )
     465             :     {
     466   138535953 :         x11 = singularVector[ch][currentIndex2];
     467   138535953 :         x12 = singularVector[ch][currentIndex1];
     468   138535953 :         singularVector[ch][currentIndex2] = ( c * x11 + s * x12 );
     469   138535953 :         singularVector[ch][currentIndex1] = ( c * x12 - s * x11 );
     470             :     }
     471             : 
     472    27961272 :     return;
     473             : }
     474             : 
     475             : 
     476             : /*-------------------------------------------------------------------------
     477             :  * HouseholderReduction()
     478             :  *
     479             :  *
     480             :  *-------------------------------------------------------------------------*/
     481             : 
     482     3053268 : static void HouseholderReduction(
     483             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],
     484             :     float singularValues[MAX_OUTPUT_CHANNELS],
     485             :     float singularVectors_Right[][MAX_OUTPUT_CHANNELS],
     486             :     float secDiag[MAX_OUTPUT_CHANNELS],
     487             :     const int16_t nChannelsL,
     488             :     const int16_t nChannelsC,
     489             :     float *eps_x )
     490             : {
     491             :     int16_t nCh;
     492     3053268 :     float g = 0.0f, sig_x = 0.0f;
     493             : 
     494             :     /* Bidiagonal Reduction for every channel */
     495    12412893 :     for ( nCh = 0; nCh < nChannelsC; nCh++ ) /* nChannelsC */
     496             :     {
     497     9359625 :         biDiagonalReductionLeft( singularVectors_Left, singularValues, secDiag, nChannelsL, nChannelsC, nCh, &sig_x, &g );
     498     9359625 :         biDiagonalReductionRight( singularVectors_Left, secDiag, nChannelsL, nChannelsC, nCh, &sig_x, &g );
     499     9359625 :         *eps_x = max( *eps_x, ( fabsf( singularValues[nCh] ) + fabsf( secDiag[nCh] ) ) );
     500             :     }
     501             : 
     502             :     /* SingularVecotr Accumulation */
     503     3053268 :     singularVectorsAccumulationRight( singularVectors_Left, singularVectors_Right, secDiag, nChannelsC );
     504     3053268 :     singularVectorsAccumulationLeft( singularVectors_Left, singularValues, nChannelsL, nChannelsC );
     505             : 
     506     3053268 :     return;
     507             : }
     508             : 
     509             : 
     510             : /*-------------------------------------------------------------------------
     511             :  * biDiagonalReductionLeft()
     512             :  *
     513             :  *
     514             :  *-------------------------------------------------------------------------*/
     515             : 
     516     9359625 : static void biDiagonalReductionLeft(
     517             :     float singularVectors[][MAX_OUTPUT_CHANNELS],
     518             :     float singularValues[MAX_OUTPUT_CHANNELS],
     519             :     float secDiag[MAX_OUTPUT_CHANNELS],
     520             :     const int16_t nChannelsL,
     521             :     const int16_t nChannelsC,
     522             :     const int16_t currChannel,
     523             :     float *sig_x,
     524             :     float *g )
     525             : {
     526             :     int16_t iCh, jCh, idx;
     527             :     float norm_x, f, r;
     528             : 
     529     9359625 :     secDiag[currChannel] = ( *sig_x ) * ( *g );
     530             : 
     531             :     /* Setting values to 0 */
     532     9359625 :     ( *sig_x ) = 0.0f;
     533     9359625 :     ( *g ) = 0.0f;
     534             : 
     535     9359625 :     if ( currChannel < nChannelsL ) /* i <= m */
     536             :     {
     537     9359625 :         idx = currChannel;
     538             : 
     539    34467297 :         for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */
     540             :         {
     541    25107672 :             ( *sig_x ) += fabsf( singularVectors[jCh][currChannel] );
     542             :         }
     543             : 
     544     9359625 :         if ( ( *sig_x ) ) /*(fabsf(*sig_x) > EPSILON * fabsf(*sig_x)) { */
     545             :         {
     546     8826147 :             norm_x = 0.0f;
     547             : 
     548    33381693 :             for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */
     549             :             {
     550    24555546 :                 singularVectors[jCh][currChannel] = ( singularVectors[jCh][currChannel] / maxWithSign( ( *sig_x ) ) );
     551    24555546 :                 norm_x += ( singularVectors[jCh][currChannel] * singularVectors[jCh][currChannel] );
     552             :             }
     553     8826147 :             ( *g ) = -( singularVectors[currChannel][idx] >= 0 ? 1 : ( -1 ) ) * sqrtf( norm_x );
     554     8826147 :             r = ( *g ) * singularVectors[currChannel][idx] - norm_x;
     555     8826147 :             singularVectors[currChannel][idx] = ( singularVectors[currChannel][idx] - ( *g ) );
     556             : 
     557    22008528 :             for ( iCh = currChannel + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */
     558             :             {
     559    13182381 :                 norm_x = 0.0f;
     560    65913204 :                 for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */
     561             :                 {
     562    52730823 :                     norm_x += ( singularVectors[jCh][currChannel] * singularVectors[jCh][iCh] );
     563             :                 }
     564             : 
     565    13182381 :                 f = norm_x / maxWithSign( r );
     566             : 
     567             : 
     568    65913204 :                 for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */
     569             :                 {
     570    52730823 :                     singularVectors[jCh][iCh] += ( f * singularVectors[jCh][currChannel] );
     571             :                 }
     572             :             }
     573             : 
     574             : 
     575    33381693 :             for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */
     576             :             {
     577    24555546 :                 singularVectors[jCh][currChannel] = ( singularVectors[jCh][currChannel] * ( *sig_x ) );
     578             :             }
     579             :         }
     580             : 
     581     9359625 :         singularValues[currChannel] = ( ( *sig_x ) * ( *g ) );
     582             :     }
     583             : 
     584     9359625 :     return;
     585             : }
     586             : 
     587             : 
     588             : /*-------------------------------------------------------------------------
     589             :  * biDiagonalReductionRight()
     590             :  *
     591             :  *
     592             :  *-------------------------------------------------------------------------*/
     593             : 
     594     9359625 : static void biDiagonalReductionRight(
     595             :     float singularVectors[][MAX_OUTPUT_CHANNELS],
     596             :     float secDiag[MAX_OUTPUT_CHANNELS],
     597             :     const int16_t nChannelsL,
     598             :     const int16_t nChannelsC,
     599             :     const int16_t currChannel,
     600             :     float *sig_x,
     601             :     float *g )
     602             : {
     603             :     int16_t iCh, jCh, idx;
     604             :     float norm_x, r;
     605             : 
     606             :     /* Setting values to 0 */
     607     9359625 :     ( *sig_x ) = 0.0f;
     608     9359625 :     ( *g ) = 0.0f;
     609             : 
     610     9359625 :     if ( currChannel < nChannelsL && currChannel != ( nChannelsC - 1 ) ) /* i <=m && i !=n */
     611             :     {
     612     6306357 :         idx = currChannel + 1;
     613             : 
     614    19507224 :         for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */
     615             :         {
     616    13200867 :             ( *sig_x ) += fabsf( singularVectors[currChannel][jCh] );
     617             :         }
     618             : 
     619     6306357 :         if ( ( *sig_x ) ) /*(fabsf(*sig_x) > EPSILON * fabsf(*sig_x)) { */
     620             :         {
     621     5813127 :             norm_x = 0.0f;
     622             : 
     623    18517782 :             for ( jCh = idx; jCh < nChannelsC; jCh++ ) /*nChannelsC */
     624             :             {
     625    12704655 :                 singularVectors[currChannel][jCh] = ( singularVectors[currChannel][jCh] / maxWithSign( ( *sig_x ) ) );
     626    12704655 :                 norm_x += ( singularVectors[currChannel][jCh] * singularVectors[currChannel][jCh] );
     627             :             }
     628     5813127 :             ( *g ) = -( singularVectors[currChannel][idx] >= 0 ? 1 : ( -1 ) ) * sqrtf( norm_x );
     629     5813127 :             r = ( *g ) * singularVectors[currChannel][idx] - norm_x;
     630     5813127 :             singularVectors[currChannel][idx] = ( singularVectors[currChannel][idx] - ( *g ) );
     631             : 
     632    18517782 :             for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */
     633             :             {
     634    12704655 :                 secDiag[jCh] = singularVectors[currChannel][jCh] / maxWithSign( r );
     635             :             }
     636             : 
     637    19804545 :             for ( iCh = currChannel + 1; iCh < nChannelsL; iCh++ ) /*  nChannelsL */
     638             :             {
     639    13991418 :                 norm_x = 0.0f;
     640    53061972 :                 for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */
     641             :                 {
     642    39070554 :                     norm_x += ( singularVectors[iCh][jCh] * singularVectors[currChannel][jCh] );
     643             :                 }
     644             : 
     645    53061972 :                 for ( jCh = idx; jCh < nChannelsC; jCh++ ) /*  nChannelsC */
     646             :                 {
     647    39070554 :                     singularVectors[iCh][jCh] += ( norm_x * secDiag[jCh] );
     648             :                 }
     649             :             }
     650             : 
     651    18517782 :             for ( jCh = idx; jCh < nChannelsC; jCh++ ) /*  nChannelsC */
     652             :             {
     653    12704655 :                 singularVectors[currChannel][jCh] = ( singularVectors[currChannel][jCh] * ( *sig_x ) );
     654             :             }
     655             :         }
     656             :     }
     657             : 
     658     9359625 :     return;
     659             : }
     660             : 
     661             : 
     662             : /*-------------------------------------------------------------------------
     663             :  * singularVectorsAccumulationLeft()
     664             :  *
     665             :  *
     666             :  *-------------------------------------------------------------------------*/
     667             : 
     668     3053268 : static void singularVectorsAccumulationLeft(
     669             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],
     670             :     float singularValues[MAX_OUTPUT_CHANNELS],
     671             :     const int16_t nChannelsL,
     672             :     const int16_t nChannelsC )
     673             : {
     674             :     int16_t nCh, iCh, k;
     675             :     int16_t nChannels;
     676             :     float norm_y, t_jj, t_ii;
     677             : 
     678             :     /* Processing */
     679     3053268 :     nChannels = min( nChannelsL, nChannelsC ); /* min(nChannelsL,ChannelsC) */
     680             : 
     681    12412893 :     for ( nCh = nChannels - 1; nCh >= 0; nCh-- ) /* min(nChannelsL,ChannelsC) */
     682             :     {
     683     9359625 :         t_ii = singularValues[nCh];
     684             : 
     685    22560492 :         for ( iCh = nCh + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */
     686             :         {
     687    13200867 :             singularVectors_Left[nCh][iCh] = 0.0f;
     688             :         }
     689             : 
     690     9359625 :         if ( t_ii ) /*if (fabsf(t_ii) > EPSILON *fabsf(t_ii)) {*/
     691             :         {
     692     8826147 :             t_ii = 1.0f / maxWithSign( t_ii );
     693             : 
     694             : 
     695    22008528 :             for ( iCh = nCh + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */
     696             :             {
     697    13182381 :                 norm_y = 0.0f;
     698    52730823 :                 for ( k = nCh + 1; k < nChannelsL; k++ ) /* nChannelsL */
     699             :                 {
     700    39548442 :                     norm_y += ( singularVectors_Left[k][nCh] * singularVectors_Left[k][iCh] );
     701             :                 }
     702    13182381 :                 t_jj = t_ii * norm_y / maxWithSign( singularVectors_Left[nCh][nCh] );
     703             : 
     704    65913204 :                 for ( k = nCh; k < nChannelsL; k++ ) /* nChannelsL */
     705             :                 {
     706    52730823 :                     singularVectors_Left[k][iCh] += ( t_jj * singularVectors_Left[k][nCh] );
     707             :                 }
     708             :             }
     709             : 
     710    33381693 :             for ( iCh = nCh; iCh < nChannelsL; iCh++ ) /* nChannelsL */
     711             :             {
     712    24555546 :                 singularVectors_Left[iCh][nCh] = ( singularVectors_Left[iCh][nCh] * t_ii );
     713             :             }
     714             :         }
     715             :         else
     716             :         {
     717     1085604 :             for ( iCh = nCh; iCh < nChannelsL; iCh++ ) /* nChannelsL */
     718             :             {
     719      552126 :                 singularVectors_Left[iCh][nCh] = 0.0f;
     720             :             }
     721             :         }
     722             : 
     723     9359625 :         ++singularVectors_Left[nCh][nCh];
     724             :     }
     725             : 
     726     3053268 :     return;
     727             : }
     728             : 
     729             : 
     730             : /*-------------------------------------------------------------------------
     731             :  * singularVectorsAccumulationRight()
     732             :  *
     733             :  *
     734             :  *-------------------------------------------------------------------------*/
     735             : 
     736     3053268 : static void singularVectorsAccumulationRight(
     737             :     float singularVectors_Left[][MAX_OUTPUT_CHANNELS],
     738             :     float singularVectors_Right[][MAX_OUTPUT_CHANNELS],
     739             :     float secDiag[MAX_OUTPUT_CHANNELS],
     740             :     const int16_t nChannelsC )
     741             : {
     742             :     int16_t nCh, iCh, k;
     743             :     int16_t nChannels;
     744             :     float norm_y, t_ii, ratio;
     745             : 
     746             :     /* Processing */
     747     3053268 :     nChannels = nChannelsC; /* nChannelsC */
     748             : 
     749             :     /* avoid compiler warning */
     750     3053268 :     t_ii = secDiag[nChannels - 1];
     751             : 
     752    12412893 :     for ( nCh = nChannels - 1; nCh >= 0; nCh-- ) /* nChannelsC, min(nChannelsLmnChannelsC) otherwise */
     753             :     {
     754             : 
     755     9359625 :         if ( nCh < nChannelsC - 1 ) /* nChannelsC */
     756             :         {
     757     6306357 :             if ( t_ii ) /*if (fabsf(t_ii) > EPSILON *fabsf(t_ii)) {*/
     758             :             {
     759             : 
     760    18517782 :                 for ( iCh = nCh + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC*/
     761             :                 {
     762    12704655 :                     ratio = singularVectors_Left[nCh][iCh] / maxWithSign( singularVectors_Left[nCh][nCh + 1] );
     763    12704655 :                     singularVectors_Right[iCh][nCh] = ratio / maxWithSign( t_ii );
     764             :                 }
     765             : 
     766    18517782 :                 for ( iCh = nCh + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */
     767             :                 {
     768    12704655 :                     norm_y = 0.0f;
     769             : 
     770    50461776 :                     for ( k = nCh + 1; k < nChannelsC; k++ ) /* nChannelsC */
     771             :                     {
     772    37757121 :                         norm_y += ( singularVectors_Left[nCh][k] * singularVectors_Right[k][iCh] );
     773             :                     }
     774             : 
     775    50461776 :                     for ( k = nCh + 1; k < nChannelsC; k++ ) /* nChannelsC */
     776             :                     {
     777    37757121 :                         singularVectors_Right[k][iCh] += ( norm_y * singularVectors_Right[k][nCh] );
     778             :                     }
     779             :                 }
     780             :             }
     781             : 
     782    19507224 :             for ( iCh = nCh + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */
     783             :             {
     784    13200867 :                 singularVectors_Right[nCh][iCh] = singularVectors_Right[iCh][nCh] = 0.0f;
     785             :             }
     786             :         }
     787     9359625 :         singularVectors_Right[nCh][nCh] = 1.0f;
     788     9359625 :         t_ii = secDiag[nCh];
     789             :     }
     790             : 
     791     3053268 :     return;
     792             : }
     793             : 
     794             : 
     795             : /*-------------------------------------------------------------------------
     796             :  * GivensRotation()
     797             :  *
     798             :  *
     799             :  *-------------------------------------------------------------------------*/
     800             : 
     801    33902376 : static float GivensRotation(
     802             :     const float x,
     803             :     const float z )
     804             : {
     805             :     float x_abs, z_abs;
     806             :     float cotan, tan, r;
     807    33902376 :     x_abs = fabsf( x );
     808    33902376 :     z_abs = fabsf( z );
     809    33902376 :     if ( x_abs <= CONVERGENCE_FACTOR * x_abs && z_abs <= CONVERGENCE_FACTOR * z_abs )
     810             :     {
     811        4812 :         r = 0.0f;
     812             :     }
     813    33897564 :     else if ( x_abs >= z_abs )
     814             :     {
     815    25667235 :         if ( x_abs <= SVD_MINIMUM_VALUE )
     816             :         {
     817           0 :             r = 0.0f;
     818             :         }
     819             :         else
     820             :         {
     821    25667235 :             cotan = z_abs / ( x_abs );
     822    25667235 :             r = x_abs * sqrtf( 1.0f + cotan * cotan );
     823             :         }
     824             :     }
     825             :     else
     826             :     {
     827     8230329 :         if ( z_abs <= SVD_MINIMUM_VALUE )
     828             :         {
     829           0 :             r = 0.0f;
     830             :         }
     831             :         else
     832             :         {
     833     8230329 :             tan = x_abs / ( z_abs );
     834     8230329 :             r = z_abs * sqrtf( 1.0f + tan * tan );
     835             :         }
     836             :     }
     837             : 
     838    33902376 :     return ( r );
     839             : }
     840             : 
     841             : 
     842             : /*-------------------------------------------------------------------------
     843             :  * maxWithSign()
     844             :  *
     845             :  *
     846             :  *-------------------------------------------------------------------------*/
     847             : 
     848   156582261 : static float maxWithSign(
     849             :     const float a )
     850             : {
     851   156582261 :     if ( fabsf( a ) > SVD_MINIMUM_VALUE )
     852             :     {
     853   156582261 :         return a;
     854             :     }
     855           0 :     else if ( a < 0.0f )
     856             :     {
     857           0 :         return -SVD_MINIMUM_VALUE;
     858             :     }
     859             :     else
     860             :     {
     861           0 :         return SVD_MINIMUM_VALUE;
     862             :     }
     863             : }
     864             : 
     865             : 
     866             : /*-------------------------------------------------------------------------
     867             :  * flushToZeroArray()
     868             :  *
     869             :  *
     870             :  *-------------------------------------------------------------------------*/
     871             : 
     872     3053268 : static void flushToZeroArray(
     873             :     float arr[MAX_OUTPUT_CHANNELS],
     874             :     const int16_t length )
     875             : {
     876             :     int16_t i;
     877             : 
     878    13673148 :     for ( i = 0; i < length; ++i )
     879             :     {
     880    10619880 :         if ( fabsf( arr[i] ) < SVD_ZERO_FLUSH_THRESHOLD )
     881             :         {
     882      555084 :             arr[i] = 0.0f;
     883             :         }
     884             :     }
     885             : 
     886     3053268 :     return;
     887             : }
     888             : 
     889             : 
     890             : /*-------------------------------------------------------------------------
     891             :  * flushToZeroMat()
     892             :  *
     893             :  *
     894             :  *-------------------------------------------------------------------------*/
     895             : 
     896     6106536 : static void flushToZeroMat(
     897             :     float mat[][MAX_OUTPUT_CHANNELS],
     898             :     const int16_t m,
     899             :     const int16_t n )
     900             : {
     901             :     int16_t i, j;
     902             : 
     903    26086041 :     for ( i = 0; i < m; ++i )
     904             :     {
     905   100610736 :         for ( j = 0; j < n; ++j )
     906             :         {
     907    80631231 :             if ( fabsf( mat[i][j] ) < SVD_ZERO_FLUSH_THRESHOLD )
     908             :             {
     909    14080884 :                 mat[i][j] = 0.0f;
     910             :             }
     911             :         }
     912             :     }
     913             : 
     914     6106536 :     return;
     915             : }

Generated by: LCOV version 1.14