LCOV - code coverage report
Current view: top level - lib_com - ivas_pca_tools.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 6baab0c613aa6c7100498ed7b93676aa8198a493 Lines: 371 423 87.7 %
Date: 2025-05-29 08:28:55 Functions: 23 23 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 "ivas_prot.h"
      36             : #include "ivas_cnst.h"
      37             : #ifdef DEBUGGING
      38             : #include "debug.h"
      39             : #endif
      40             : #include <math.h>
      41             : #include <assert.h>
      42             : #include "ivas_rom_com.h"
      43             : #include "wmc_auto.h"
      44             : #include "prot.h"
      45             : 
      46             : 
      47             : /*---------------------------------------------------------------------*
      48             :  * eye_matrix()
      49             :  *
      50             :  *---------------------------------------------------------------------*/
      51             : 
      52    30117065 : void eye_matrix(
      53             :     float *mat,
      54             :     const int16_t n,
      55             :     const float d )
      56             : {
      57             :     int16_t i;
      58             : 
      59   511990105 :     for ( i = 0; i < n * n; i++ )
      60             :     {
      61   481873040 :         mat[i] = 0.0f;
      62             :     }
      63   150585325 :     for ( i = 0; i < n; i++ )
      64             :     {
      65   120468260 :         mat[i * n + i] = d;
      66             :     }
      67             : 
      68    30117065 :     return;
      69             : }
      70             : 
      71             : 
      72             : /*---------------------------------------------------------------------*
      73             :  * cov()
      74             :  *
      75             :  * Compute covariance of input channels
      76             :  *---------------------------------------------------------------------*/
      77             : 
      78       69012 : void cov_subfr(
      79             :     float **ptr_sig,
      80             :     float *r,
      81             :     const int16_t n_channels,
      82             :     const int16_t len )
      83             : {
      84             :     float s;
      85             :     int16_t j, k, l;
      86             :     float *t, *tt;
      87             : 
      88             :     /* Compute diagonal r[k][k] */
      89      345060 :     for ( k = 0; k < n_channels; k++ )
      90             :     {
      91      276048 :         t = &ptr_sig[k][0];
      92      276048 :         s = t[0] * t[0];
      93   100097280 :         for ( j = 1; j < len; j++ )
      94             :         {
      95    99821232 :             s += t[j] * t[j];
      96             :         }
      97      276048 :         r[k * n_channels + k] = s;
      98             :     }
      99             : 
     100             :     /* Compute off-diagonal r[k][l] = r[l][k] */
     101      276048 :     for ( k = 0; k < ( n_channels - 1 ); k++ )
     102             :     {
     103      207036 :         t = &ptr_sig[k][0];
     104      621108 :         for ( l = k + 1; l < n_channels; l++ )
     105             :         {
     106      414072 :             tt = &ptr_sig[l][0];
     107      414072 :             s = t[0] * tt[0];
     108   150145920 :             for ( j = 1; j < len; j++ )
     109             :             {
     110   149731848 :                 s += t[j] * tt[j];
     111             :             }
     112      414072 :             r[k * n_channels + l] = s;
     113      414072 :             r[l * n_channels + k] = s;
     114             :         }
     115             :     }
     116             : 
     117       69012 :     return;
     118             : }
     119             : 
     120             : 
     121     1380240 : static void house_refl(
     122             :     const float *px,
     123             :     const int16_t sizex,
     124             :     float *pu,
     125             :     float *normu )
     126             : {
     127             :     int16_t i;
     128             : 
     129     1380240 :     mvr2r( px, pu, sizex );
     130     1380240 :     ( *normu ) = dotp( pu, pu, sizex );
     131     1380240 :     ( *normu ) = sqrtf( *normu );
     132             : 
     133     1380240 :     if ( ( *normu ) == 0.f )
     134             :     {
     135           0 :         pu[0] = SQRT2;
     136             :     }
     137             :     else
     138             :     {
     139     1380240 :         float rcp = 1.f / ( *normu );
     140             : 
     141     4830840 :         for ( i = 0; i < sizex; i++ )
     142             :         {
     143     3450600 :             pu[i] *= rcp;
     144             :         }
     145     1380240 :         if ( pu[0] >= 0.f )
     146             :         {
     147     1380240 :             pu[0] += 1;
     148     1380240 :             ( *normu ) = -( *normu );
     149             :         }
     150             :         else
     151             :         {
     152           0 :             pu[0] -= 1;
     153             :         }
     154             : 
     155     1380240 :         rcp = inv_sqrt( fabsf( pu[0] ) );
     156             : 
     157     4830840 :         for ( i = 0; i < sizex; i++ )
     158             :         {
     159     3450600 :             pu[i] *= rcp;
     160             :         }
     161             :     }
     162             : 
     163     1380240 :     return;
     164             : }
     165             : 
     166             : 
     167      345060 : static void house_qr(
     168             :     const float *pA,
     169             :     float *pQ,
     170             :     float *pR,
     171             :     const int16_t n )
     172             : {
     173      345060 :     int16_t n_rows = FOA_CHANNELS;
     174             :     float A[FOA_CHANNELS * FOA_CHANNELS];
     175             :     float U[FOA_CHANNELS * FOA_CHANNELS];
     176             :     float pu[FOA_CHANNELS];
     177             :     float pa[FOA_CHANNELS];
     178             :     float pv[FOA_CHANNELS];
     179             :     int16_t i, j, k, c, s, r;
     180             : 
     181      345060 :     mvr2r( pA, A, FOA_CHANNELS * FOA_CHANNELS );
     182      345060 :     set_zero( U, FOA_CHANNELS * FOA_CHANNELS );
     183      345060 :     set_zero( pR, FOA_CHANNELS * FOA_CHANNELS );
     184             : 
     185     1725300 :     for ( k = 0; k < n_rows; k++ )
     186             :     {
     187     6901200 :         for ( i = 0; i < n_rows; i++ )
     188             :         {
     189     5520960 :             pa[i] = A[i * n + k];
     190             :         }
     191             : 
     192     1380240 :         house_refl( &pa[k], n_rows - k, pu, &pR[k * n_rows + k] );
     193     1380240 :         U[k * n_rows + k] = pu[0];
     194     3450600 :         for ( c = k + 1; c < n_rows; c++ )
     195             :         {
     196    10351800 :             for ( i = 0; i < n_rows; i++ )
     197             :             {
     198     8281440 :                 pa[i] = A[i * n + c];
     199             :             }
     200     2070360 :             pv[c - k - 1] = dotp( pu, &pa[k], n_rows - k );
     201     2070360 :             U[c * n_rows + k] = pu[c - k];
     202             :         }
     203             : 
     204     1380240 :         i = 0;
     205     4830840 :         for ( s = k; s < n_rows; s++ )
     206             :         {
     207     3450600 :             j = 0;
     208    10351800 :             for ( r = k + 1; r < n_rows; r++ )
     209             :             {
     210     6901200 :                 A[s * n_rows + r] -= ( pu[i] * pv[j] );
     211     6901200 :                 j++;
     212             :             }
     213     3450600 :             i++;
     214             :         }
     215             : 
     216     3450600 :         for ( r = k + 1; r < n_rows; r++ )
     217             :         {
     218     2070360 :             pR[k * n_rows + r] = A[k * n_rows + r];
     219             :         }
     220             :     }
     221             : 
     222      345060 :     eye_matrix( pQ, FOA_CHANNELS, 1.0f );
     223             : 
     224     1725300 :     for ( k = FOA_CHANNELS - 1; k >= 0; k-- )
     225             :     {
     226     6901200 :         for ( i = 0; i < n_rows; i++ )
     227             :         {
     228     5520960 :             pu[i] = U[i * n + k];
     229             :         }
     230             : 
     231     4830840 :         for ( s = k; s < n_rows; s++ )
     232             :         {
     233    17253000 :             for ( i = 0; i < n_rows; i++ )
     234             :             {
     235    13802400 :                 pa[i] = pQ[i * n + s];
     236             :             }
     237     3450600 :             pv[s - k] = dotp( &pu[k], &pa[k], n_rows - k );
     238             :         }
     239     4830840 :         for ( s = k; s < n_rows; s++ )
     240             :         {
     241    13802400 :             for ( r = k; r < n_rows; r++ )
     242             :             {
     243    10351800 :                 pQ[s * n_rows + r] -= U[s * n_rows + k] * pv[r - k];
     244             :             }
     245             :         }
     246             :     }
     247             : 
     248      345060 :     return;
     249             : }
     250             : 
     251             : 
     252             : /*---------------------------------------------------------------------*
     253             :  * eig_qr()
     254             :  *
     255             :  * Compute eigenvalue decomposition by QR method
     256             :  *---------------------------------------------------------------------*/
     257             : 
     258       34506 : void eig_qr(
     259             :     const float *A,
     260             :     const int16_t num_iter,
     261             :     float *EV,
     262             :     float *Vals,
     263             :     const int16_t n )
     264             : {
     265             :     int16_t i;
     266             :     int16_t breakcnd, iter_num;
     267             :     float Ak[FOA_CHANNELS * FOA_CHANNELS], Qk[FOA_CHANNELS * FOA_CHANNELS], Rk[FOA_CHANNELS * FOA_CHANNELS], D[FOA_CHANNELS * FOA_CHANNELS], d;
     268             : 
     269       34506 :     assert( n <= FOA_CHANNELS );
     270       34506 :     breakcnd = 1;
     271       34506 :     iter_num = 0;
     272             : 
     273             :     /* check zero matrix */
     274       34506 :     d = dotp( A, A, n * n );
     275       34506 :     if ( d != 0. )
     276             :     {
     277       34506 :         breakcnd = 0;
     278             :     }
     279             : 
     280             :     /* duplicate */
     281       34506 :     mvr2r( A, Ak, n * n );
     282             : 
     283             :     /* identity */
     284       34506 :     set_zero( EV, n * n );
     285      172530 :     for ( i = 0; i < n; i++ )
     286             :     {
     287      138024 :         EV[i * n + i] = 1.0f;
     288             :     }
     289             : 
     290       34506 :     set_zero( Vals, n );
     291             : 
     292      379566 :     while ( breakcnd == 0 )
     293             :     {
     294      345060 :         iter_num++;
     295      345060 :         mvr2r( Ak, D, n * n );
     296             : 
     297             :         /* set diagonal */
     298     1725300 :         for ( i = 0; i < n; i++ )
     299             :         {
     300     1380240 :             D[i * n + i] = Vals[i];
     301             :         }
     302             : 
     303             :         /* stop condition */
     304      345060 :         d = dotp( D, D, n * n );
     305      345060 :         d = sqrtf( d ); /* Frobenius norm */
     306             : 
     307      345060 :         if ( ( d < 1e-10f ) || ( iter_num >= num_iter ) )
     308             :         {
     309       34506 :             breakcnd = 1;
     310             :         }
     311             : 
     312      345060 :         house_qr( Ak, Qk, Rk, n );
     313             : 
     314      345060 :         matrix_product( Qk, n, n, 0, Rk, n, n, 0, Ak );
     315      345060 :         matrix_product( Qk, n, n, 0, EV, n, n, 0, D );
     316             : 
     317      345060 :         mvr2r( D, EV, n * n );
     318             :     }
     319             : 
     320             :     /* get diagonal */
     321      172530 :     for ( i = 0; i < n; i++ )
     322             :     {
     323      138024 :         Vals[i] = Ak[i * n + i];
     324             :     }
     325             : 
     326       34506 :     return;
     327             : }
     328             : 
     329             : 
     330             : /*---------------------------------------------------------------------*
     331             :  * exhst_4x4()
     332             :  *
     333             :  * Find optimal permutation of eigenvectors
     334             :  *---------------------------------------------------------------------*/
     335             : 
     336         372 : void exhst_4x4(
     337             :     float *cost_mtx,
     338             :     int16_t *path,
     339             :     const int16_t maximize )
     340             : {
     341             :     int16_t i, j, k, l;
     342             :     float opt_val, cost;
     343             : 
     344         372 :     if ( maximize == 0 )
     345             :     {
     346           0 :         opt_val = 1e30f;
     347             :     }
     348             :     else
     349             :     {
     350         372 :         opt_val = -1e30f;
     351             :     }
     352             : 
     353         744 :     for ( i = 0; i < 1; i++ )
     354             :     {
     355        1860 :         for ( j = 0; j < 4; j++ )
     356             :         {
     357        1488 :             if ( j != i )
     358             :             {
     359        5580 :                 for ( k = 0; k < 4; k++ )
     360             :                 {
     361        4464 :                     if ( ( k != i ) && ( k != j ) )
     362             :                     {
     363       11160 :                         for ( l = 0; l < 4; l++ )
     364             :                         {
     365        8928 :                             if ( ( l != i ) && ( l != j ) && ( l != k ) )
     366             :                             {
     367        2232 :                                 cost = cost_mtx[0 * 4 + i] + cost_mtx[1 * 4 + j] + cost_mtx[2 * 4 + k] + cost_mtx[3 * 4 + l];
     368        2232 :                                 if ( ( ( maximize == 0 ) && ( opt_val > cost ) ) || ( ( maximize != 0 ) && ( opt_val < cost ) ) )
     369             :                                 {
     370         439 :                                     opt_val = cost;
     371         439 :                                     path[0] = i;
     372         439 :                                     path[1] = j;
     373         439 :                                     path[2] = k;
     374         439 :                                     path[3] = l;
     375             :                                 }
     376             :                             }
     377             :                         }
     378             :                     }
     379             :                 }
     380             :             }
     381             :         }
     382             :     }
     383             : 
     384         372 :     return;
     385             : }
     386             : 
     387             : 
     388             : /*---------------------------------------------------------------------*
     389             :  * mat2dquat()
     390             :  *
     391             :  * Convert 4D matrix -> double quaternion
     392             :  *---------------------------------------------------------------------*/
     393             : 
     394       34506 : void mat2dquat(
     395             :     const float *a,
     396             :     float *ql,
     397             :     float *qr )
     398             : {
     399             :     float AM[16], M2[16], tmp_l, tmp_r, temp, ql_max, qr_max;
     400             :     int16_t i, j, k, i_ql, i_qr;
     401             : 
     402             :     /* compute associate matrix */
     403       34506 :     AM[0 * 4 + 0] = ( a[0 * 4 + 0] + a[1 * 4 + 1] + a[2 * 4 + 2] + a[3 * 4 + 3] ) / 4.0f;
     404       34506 :     AM[1 * 4 + 0] = ( a[1 * 4 + 0] - a[0 * 4 + 1] + a[3 * 4 + 2] - a[2 * 4 + 3] ) / 4.0f;
     405       34506 :     AM[2 * 4 + 0] = ( a[2 * 4 + 0] - a[3 * 4 + 1] - a[0 * 4 + 2] + a[1 * 4 + 3] ) / 4.0f;
     406       34506 :     AM[3 * 4 + 0] = ( a[3 * 4 + 0] + a[2 * 4 + 1] - a[1 * 4 + 2] - a[0 * 4 + 3] ) / 4.0f;
     407       34506 :     AM[0 * 4 + 1] = ( a[1 * 4 + 0] - a[0 * 4 + 1] - a[3 * 4 + 2] + a[2 * 4 + 3] ) / 4.0f;
     408       34506 :     AM[1 * 4 + 1] = ( -a[0 * 4 + 0] - a[1 * 4 + 1] + a[2 * 4 + 2] + a[3 * 4 + 3] ) / 4.0f;
     409       34506 :     AM[2 * 4 + 1] = ( -a[3 * 4 + 0] - a[2 * 4 + 1] - a[1 * 4 + 2] - a[0 * 4 + 3] ) / 4.0f;
     410       34506 :     AM[3 * 4 + 1] = ( a[2 * 4 + 0] - a[3 * 4 + 1] + a[0 * 4 + 2] - a[1 * 4 + 3] ) / 4.0f;
     411       34506 :     AM[0 * 4 + 2] = ( a[2 * 4 + 0] + a[3 * 4 + 1] - a[0 * 4 + 2] - a[1 * 4 + 3] ) / 4.0f;
     412       34506 :     AM[1 * 4 + 2] = ( a[3 * 4 + 0] - a[2 * 4 + 1] - a[1 * 4 + 2] + a[0 * 4 + 3] ) / 4.0f;
     413       34506 :     AM[2 * 4 + 2] = ( -a[0 * 4 + 0] + a[1 * 4 + 1] - a[2 * 4 + 2] + a[3 * 4 + 3] ) / 4.0f;
     414       34506 :     AM[3 * 4 + 2] = ( -a[1 * 4 + 0] - a[0 * 4 + 1] - a[3 * 4 + 2] - a[2 * 4 + 3] ) / 4.0f;
     415       34506 :     AM[0 * 4 + 3] = ( a[3 * 4 + 0] - a[2 * 4 + 1] + a[1 * 4 + 2] - a[0 * 4 + 3] ) / 4.0f;
     416       34506 :     AM[1 * 4 + 3] = ( -a[2 * 4 + 0] - a[3 * 4 + 1] - a[0 * 4 + 2] - a[1 * 4 + 3] ) / 4.0f;
     417       34506 :     AM[2 * 4 + 3] = ( a[1 * 4 + 0] + a[0 * 4 + 1] - a[3 * 4 + 2] - a[2 * 4 + 3] ) / 4.0f;
     418       34506 :     AM[3 * 4 + 3] = ( -a[0 * 4 + 0] + a[1 * 4 + 1] + a[2 * 4 + 2] - a[3 * 4 + 3] ) / 4.0f;
     419             : 
     420             :     /* compute squared matrix */
     421      586602 :     for ( i = 0; i < 16; i++ )
     422             :     {
     423      552096 :         M2[i] = AM[i] * AM[i];
     424             :     }
     425             : 
     426             :     /* determine (absolute) left and right terms */
     427       34506 :     i_ql = 0;
     428       34506 :     i_qr = 0;
     429       34506 :     ql_max = -1;
     430       34506 :     qr_max = -1;
     431             : 
     432      172530 :     for ( i = 0; i < 4; i++ )
     433             :     {
     434      138024 :         tmp_l = 0.f;
     435      138024 :         tmp_r = 0.f;
     436      690120 :         for ( j = 0; j < 4; j++ )
     437             :         {
     438             :             /* sum over row */
     439      552096 :             tmp_l += M2[i * 4 + j];
     440             :             /* sum over column */
     441      552096 :             tmp_r += M2[j * 4 + i];
     442             :         }
     443             : 
     444      138024 :         ql[i] = sqrtf( tmp_l );
     445      138024 :         if ( ql[i] > ql_max )
     446             :         {
     447       37009 :             ql_max = ql[i];
     448       37009 :             i_ql = i;
     449             :         }
     450             : 
     451      138024 :         qr[i] = sqrtf( tmp_r );
     452      138024 :         if ( qr[i] > qr_max )
     453             :         {
     454       37427 :             qr_max = qr[i];
     455       37427 :             i_qr = i;
     456             :         }
     457             :     }
     458             : 
     459             :     /* set signs */
     460      172530 :     for ( k = 0; k < 4; k++ )
     461             :     {
     462      138024 :         if ( AM[i_ql * 4 + k] < 0 )
     463             :         {
     464       58833 :             qr[k] = -qr[k];
     465             :         }
     466             :     }
     467             : 
     468      172530 :     for ( k = 0; k < 4; k++ )
     469             :     {
     470      138024 :         temp = AM[k * 4 + i_qr] * ( ql[k] * qr[i_qr] );
     471      138024 :         if ( temp < 0 )
     472             :         {
     473       47308 :             ql[k] = -ql[k];
     474             :         }
     475             :     }
     476             : 
     477       34506 :     return;
     478             : }
     479             : 
     480             : 
     481             : /*---------------------------------------------------------------------*
     482             :  * dquat2mat()
     483             :  *
     484             :  * Convert double quaternion -> 4D matrix
     485             :  *---------------------------------------------------------------------*/
     486             : 
     487     4772280 : void dquat2mat(
     488             :     const float *ql,
     489             :     const float *qr,
     490             :     float *m )
     491             : {
     492             :     float a, b, c, d;
     493             :     float w, x, y, z;
     494             :     float aw, ax, ay, az;
     495             :     float bw, bx, by, bz;
     496             :     float cw, cx, cy, cz;
     497             :     float dw, dx, dy, dz;
     498             : 
     499     4772280 :     a = ql[0];
     500     4772280 :     b = ql[1];
     501     4772280 :     c = ql[2];
     502     4772280 :     d = ql[3];
     503     4772280 :     w = qr[0];
     504     4772280 :     x = qr[1];
     505     4772280 :     y = qr[2];
     506     4772280 :     z = qr[3];
     507     4772280 :     aw = a * w;
     508     4772280 :     ax = a * x;
     509     4772280 :     ay = a * y;
     510     4772280 :     az = a * z;
     511     4772280 :     bw = b * w;
     512     4772280 :     bx = b * x;
     513     4772280 :     by = b * y;
     514     4772280 :     bz = b * z;
     515     4772280 :     cw = c * w;
     516     4772280 :     cx = c * x;
     517     4772280 :     cy = c * y;
     518     4772280 :     cz = c * z;
     519     4772280 :     dw = d * w;
     520     4772280 :     dx = d * x;
     521     4772280 :     dy = d * y;
     522     4772280 :     dz = d * z;
     523     4772280 :     m[0] = aw - bx - cy - dz;
     524     4772280 :     m[1] = -ax - bw + cz - dy;
     525     4772280 :     m[2] = -ay - bz - cw + dx;
     526     4772280 :     m[3] = -az + by - cx - dw;
     527     4772280 :     m[4] = bw + ax - dy + cz;
     528     4772280 :     m[5] = -bx + aw + dz + cy;
     529     4772280 :     m[6] = -by + az - dw - cx;
     530     4772280 :     m[7] = -bz - ay - dx + cw;
     531     4772280 :     m[8] = cw + dx + ay - bz;
     532     4772280 :     m[9] = -cx + dw - az - by;
     533     4772280 :     m[10] = -cy + dz + aw + bx;
     534     4772280 :     m[11] = -cz - dy + ax - bw;
     535     4772280 :     m[12] = dw - cx + by + az;
     536     4772280 :     m[13] = -dx - cw - bz + ay;
     537     4772280 :     m[14] = -dy - cz + bw - ax;
     538     4772280 :     m[15] = -dz + cy + bx + aw;
     539             : 
     540     4772280 :     return;
     541             : }
     542             : 
     543             : 
     544             : /*---------------------------------------------------------------------*
     545             :  * quat_shortestpath()
     546             :  *
     547             :  * Shortest path verification (prior to quaternion interpolation)
     548             :  *---------------------------------------------------------------------*/
     549             : 
     550      119307 : void quat_shortestpath(
     551             :     const float *q00,
     552             :     float *q01,
     553             :     const float *q10,
     554             :     float *q11 )
     555             : {
     556             :     float d0, d1;
     557             :     int16_t res, i;
     558             : 
     559      119307 :     d0 = dotp( q00, q01, IVAS_PCA_INTERP );
     560      119307 :     d1 = dotp( q10, q11, IVAS_PCA_INTERP );
     561             : 
     562      119307 :     res = 0;
     563      119307 :     if ( ( d0 < 0. ) && ( d1 < 0. ) )
     564             :     {
     565           0 :         res = 1;
     566             :     }
     567             :     else
     568             :     {
     569      119307 :         if ( d0 < 0. )
     570             :         {
     571           0 :             if ( ( -d0 ) > d1 )
     572             :             {
     573           0 :                 res = 1;
     574             :             }
     575             :         }
     576             :         else
     577             :         {
     578      119307 :             if ( d1 < 0. )
     579             :             {
     580           0 :                 if ( ( -d1 ) > d0 )
     581             :                 {
     582           0 :                     res = 1;
     583             :                 }
     584             :             }
     585             :         }
     586             :     }
     587             : 
     588      119307 :     if ( res )
     589             :     {
     590           0 :         for ( i = 0; i < IVAS_PCA_INTERP; i++ )
     591             :         {
     592           0 :             q01[i] = -q01[i];
     593           0 :             q11[i] = -q11[i];
     594             :         }
     595             :     }
     596             : 
     597      119307 :     return;
     598             : }
     599             : 
     600             : 
     601             : /*---------------------------------------------------------------------*
     602             :  * mat_det4()
     603             :  *
     604             :  * Compute determinant of 4D matrix - brute-force version
     605             :  *---------------------------------------------------------------------*/
     606             : 
     607       34506 : float mat_det4(
     608             :     const float *m )
     609             : {
     610             :     float d;
     611             : 
     612             : #define a11 m[0]
     613             : #define a12 m[1]
     614             : #define a13 m[2]
     615             : #define a14 m[3]
     616             : #define a21 m[4]
     617             : #define a22 m[5]
     618             : #define a23 m[6]
     619             : #define a24 m[7]
     620             : #define a31 m[8]
     621             : #define a32 m[9]
     622             : #define a33 m[10]
     623             : #define a34 m[11]
     624             : #define a41 m[12]
     625             : #define a42 m[13]
     626             : #define a43 m[14]
     627             : #define a44 m[15]
     628             : 
     629             :     /* 4! = 24 terms -> complexity = 24x(4 INDIRECT + 3 MULT) + 23 ADD */
     630       34506 :     d = a11 * a22 * a33 * a44 + a11 * a24 * a32 * a43 + a11 * a23 * a34 * a42 - a11 * a24 * a33 * a42 - a11 * a22 * a34 * a43 -
     631       34506 :         a11 * a23 * a32 * a44 - a12 * a21 * a33 * a44 - a12 * a23 * a34 * a41 - a12 * a24 * a31 * a43 + a12 * a24 * a33 * a41 +
     632       34506 :         a12 * a21 * a34 * a43 + a12 * a23 * a31 * a44 + a13 * a21 * a32 * a44 + a13 * a22 * a34 * a41 + a13 * a24 * a31 * a42 -
     633       34506 :         a13 * a24 * a32 * a41 - a13 * a21 * a34 * a42 - a13 * a22 * a31 * a44 - a14 * a21 * a32 * a43 - a14 * a22 * a33 * a41 -
     634       34506 :         a14 * a23 * a31 * a42 + a14 * a23 * a32 * a41 + a14 * a21 * a33 * a42 + a14 * a22 * a31 * a43;
     635             : 
     636       34506 :     return d;
     637             : }
     638             : 
     639             : 
     640     9544560 : static void norm_quat(
     641             :     float *q )
     642             : {
     643             :     float norm_q;
     644             :     int16_t i;
     645             : 
     646     9544560 :     norm_q = dotp( q, q, IVAS_PCA_INTERP );
     647             : 
     648     9544560 :     norm_q = inv_sqrt( norm_q ); // TODO: possible division by 0
     649             : 
     650    47722800 :     for ( i = 0; i < IVAS_PCA_INTERP; i++ )
     651             :     {
     652    38178240 :         q[i] *= norm_q;
     653             :     }
     654             : 
     655     9544560 :     return;
     656             : }
     657             : 
     658             : 
     659     9544560 : static void quat_nlerp_preproc(
     660             :     const float *q0,
     661             :     const float *q1,
     662             :     const float alpha,
     663             :     float *q_slerp )
     664             : {
     665             :     int16_t i;
     666             : 
     667    47722800 :     for ( i = 0; i < IVAS_PCA_INTERP; i++ )
     668             :     {
     669    38178240 :         q_slerp[i] = alpha * q0[i] + ( 1.0f - alpha ) * q1[i];
     670             :     }
     671             : 
     672     9544560 :     norm_quat( q_slerp );
     673             : 
     674     9544560 :     return;
     675             : }
     676             : 
     677             : 
     678      119307 : void pca_interp_preproc(
     679             :     const float *prev_ql,
     680             :     const float *prev_qr,
     681             :     const float *ql,
     682             :     const float *qr,
     683             :     const int16_t len,
     684             :     float *ql_interp,
     685             :     float *qr_interp )
     686             : {
     687             :     float alpha;
     688             :     int16_t j;
     689             : 
     690     4891587 :     for ( j = 0; j < len; j++ )
     691             :     {
     692     4772280 :         alpha = (float) j / (float) ( len - 1 ); // the increment can be updated by simple delta
     693     4772280 :         alpha = 0.5f * ( 1.f - cosf( EVS_PI * alpha ) );
     694     4772280 :         alpha = 1 - alpha;
     695     4772280 :         quat_nlerp_preproc( prev_ql, ql, alpha, &ql_interp[j * IVAS_PCA_INTERP] );
     696     4772280 :         quat_nlerp_preproc( prev_qr, qr, alpha, &qr_interp[j * IVAS_PCA_INTERP] );
     697             :     }
     698             : 
     699      119307 :     return;
     700             : }
     701             : 
     702             : 
     703        2232 : static float acos_clip(
     704             :     float v )
     705             : {
     706             :     float ph;
     707             : 
     708        2232 :     v = check_bounds( v, -1.0f, 1.0f );
     709             : 
     710        2232 :     ph = acosf( v );
     711             : 
     712        2232 :     return ph;
     713             : }
     714             : 
     715             : 
     716        4808 : static void sp2cart(
     717             :     const float ph1,
     718             :     const float ph2,
     719             :     const float ph3,
     720             :     float *q )
     721             : {
     722             :     float s1, s2, s1s2;
     723             : 
     724        4808 :     s1 = sinf( ph1 );
     725        4808 :     s2 = sinf( ph2 );
     726        4808 :     s1s2 = s1 * s2;
     727        4808 :     q[3] = sinf( ph3 ) * s1s2;
     728        4808 :     q[2] = cosf( ph3 ) * s1s2;
     729        4808 :     q[1] = cosf( ph2 ) * s1;
     730        4808 :     q[0] = cosf( ph1 );
     731             : 
     732        4808 :     return;
     733             : }
     734             : 
     735        3320 : static int16_t calc_n2(
     736             :     const float ph1 )
     737             : {
     738             :     int16_t n2;
     739             : 
     740        3320 :     n2 = (int16_t) roundf( 90.f * sinf( ph1 ) );
     741             : 
     742        3320 :     if ( n2 % 2 == 0 )
     743             :     {
     744        1605 :         n2++;
     745             :     }
     746             : 
     747        3320 :     return n2;
     748             : }
     749             : 
     750             : 
     751        4808 : static int16_t calc_n3(
     752             :     const float ph1,
     753             :     const float ph2 )
     754             : {
     755             :     int16_t n3;
     756             : 
     757        4808 :     n3 = (int16_t) roundf( 180.f * sinf( ph1 ) * sinf( ph2 ) );
     758             : 
     759        4808 :     if ( n3 == 0 )
     760             :     {
     761           0 :         n3 = 1;
     762             :     }
     763             :     else
     764             :     {
     765        4808 :         if ( ( n3 % 2 ) == 1 )
     766             :         {
     767        2426 :             n3++;
     768             :         }
     769             :     }
     770             : 
     771        4808 :     return n3;
     772             : }
     773             : 
     774             : 
     775        2232 : static void q_ang_2surv(
     776             :     const float a,
     777             :     const int16_t N,
     778             :     float *a_q,
     779             :     int16_t *index )
     780             : {
     781             :     float d, v;
     782             :     int16_t temp;
     783             : 
     784        2232 :     if ( N == 1 )
     785             :     {
     786           0 :         a_q[0] = 0.f;
     787           0 :         a_q[1] = 0.f;
     788           0 :         index[0] = 0;
     789           0 :         index[1] = 0;
     790           0 :         return;
     791             :     }
     792        2232 :     d = EVS_PI / ( N - 1 );
     793        2232 :     if ( a >= EVS_PI )
     794             :     {
     795           0 :         index[0] = N - 1;
     796           0 :         index[1] = N - 2;
     797             :     }
     798             :     else
     799             :     {
     800        2232 :         if ( a <= 0 )
     801             :         {
     802           0 :             index[0] = 0;
     803           0 :             index[1] = 1;
     804             :         }
     805             :         else
     806             :         {
     807        2232 :             v = a / d;
     808        2232 :             index[0] = (int16_t) floorf( v );
     809        2232 :             index[1] = (int16_t) ceilf( v );
     810             : 
     811        2232 :             if ( index[0] == index[1] )
     812             :             {
     813             :                 /*printf("warning: identical indices\n"); */
     814             :             }
     815             :             else
     816             :             {
     817        2232 :                 if ( ( v - index[0] ) < ( index[1] - v ) )
     818             :                 {
     819        1179 :                     temp = index[1];
     820        1179 :                     index[1] = index[0];
     821        1179 :                     index[0] = temp;
     822             :                 }
     823             :             }
     824             :         }
     825             :     }
     826        2232 :     a_q[0] = index[0] * d;
     827        2232 :     a_q[1] = index[1] * d;
     828             : 
     829        2232 :     return;
     830             : }
     831             : 
     832             : 
     833        2976 : static void q_ang_circ(
     834             :     const float a,
     835             :     const int16_t N,
     836             :     float *a_q,
     837             :     int16_t *index )
     838             : {
     839             :     float d;
     840        2976 :     if ( N == 1 )
     841             :     {
     842           0 :         *a_q = 0.f;
     843           0 :         *index = 0;
     844             : 
     845           0 :         return;
     846             :     }
     847             : 
     848        2976 :     d = PI2 / N;
     849             : 
     850        2976 :     if ( a >= PI2 )
     851             :     {
     852           0 :         *index = N;
     853             :     }
     854             :     else
     855             :     {
     856        2976 :         if ( a <= 0.f )
     857             :         {
     858           0 :             *index = 0;
     859             :         }
     860             :         else
     861             :         {
     862        2976 :             *index = (int16_t) roundf( a / d );
     863             :         }
     864             :     }
     865             : 
     866        2976 :     if ( *index == N )
     867             :     {
     868           8 :         *index = 0;
     869             :     }
     870             : 
     871        2976 :     assert( ( *index >= 0 ) && ( *index <= ( N - 1 ) ) );
     872        2976 :     *a_q = *index * d;
     873             : 
     874        2976 :     return;
     875             : }
     876             : 
     877             : 
     878         744 : static int16_t sel_q(
     879             :     const float *q,
     880             :     const float *q_cand,
     881             :     const int16_t n )
     882             : {
     883             :     int16_t i, i_min, j;
     884             :     float d, d_min, temp;
     885             :     const float *p;
     886             : 
     887         744 :     i_min = -1;
     888         744 :     d_min = 1e30f;
     889         744 :     p = q_cand;
     890             : 
     891        3720 :     for ( i = 0; i < n; i++ )
     892             :     {
     893        2976 :         d = 0.f;
     894       14880 :         for ( j = 0; j < 4; j++ )
     895             :         {
     896       11904 :             temp = q[j] - p[j];
     897       11904 :             d += temp * temp;
     898             :         }
     899             : 
     900        2976 :         if ( d < d_min )
     901             :         {
     902        2571 :             d_min = d;
     903        2571 :             i_min = i;
     904             :         }
     905        2976 :         p += 4;
     906             :     }
     907         744 :     assert( i_min >= 0 );
     908             : 
     909         744 :     return i_min;
     910             : }
     911             : 
     912             : 
     913       44181 : static int16_t get_pca_offset_n2(
     914             :     const int16_t index1 )
     915             : {
     916             :     int16_t index2;
     917             : 
     918       44181 :     if ( index1 <= IVAS_PCA_N1_EQ )
     919             :     {
     920       44181 :         index2 = ivas_pca_offset_n2[index1];
     921             :     }
     922             :     else
     923             :     {
     924           0 :         index2 = ivas_pca_offset_n2[IVAS_PCA_N1 - 1 - index1];
     925             :     }
     926             : 
     927       44181 :     return index2;
     928             : }
     929             : 
     930             : 
     931             : /*---------------------------------------------------------------------*
     932             :  * pca_enc_s3()
     933             :  *
     934             :  *
     935             :  *---------------------------------------------------------------------*/
     936             : 
     937         744 : void pca_enc_s3(
     938             :     float *q,
     939             :     int32_t *index )
     940             : {
     941             :     float ph1, ph2, ph3, r, v;
     942             :     float ph1_q[2], ph2_q[4], ph3_q[4];
     943             :     int16_t n1, n2[2], n3[4];
     944             :     int16_t ind1[2], ind2[4], ind3[4], index1, index2, index3;
     945             :     int16_t i, j;
     946             :     float q_cand[4 * 4];
     947             : 
     948         744 :     n1 = IVAS_PCA_N1;
     949         744 :     ph1 = acos_clip( q[0] );
     950         744 :     if ( fabsf( fabsf( q[0] ) - 1.0f ) < IVAS_PCA_QUAT_EPS )
     951             :     {
     952           0 :         if ( q[0] > 0 )
     953             :         {
     954           0 :             *ph1_q = 0.f;
     955           0 :             index1 = 0;
     956             :         }
     957             :         else
     958             :         {
     959           0 :             *ph1_q = EVS_PI;
     960           0 :             index1 = n1 - 1;
     961             :         }
     962             : 
     963           0 :         sp2cart( *ph1_q, 0.f, 0.f, q );
     964             : 
     965           0 :         *index = ivas_pca_offset_index1[index1];
     966             : 
     967           0 :         return;
     968             :     }
     969             : 
     970         744 :     q_ang_2surv( ph1, n1, ph1_q, ind1 );
     971             : 
     972         744 :     r = sqrtf( q[1] * q[1] + q[2] * q[2] + q[3] * q[3] );
     973             : 
     974         744 :     v = q[1] / r;
     975         744 :     ph2 = acos_clip( v );
     976             : 
     977         744 :     if ( fabs( fabs( v ) - 1.0f ) < IVAS_PCA_QUAT_EPS )
     978             :     {
     979           0 :         for ( i = 0; i < 2; i++ )
     980             :         {
     981           0 :             n2[i] = calc_n2( ph1_q[i] );
     982           0 :             if ( v > 0 )
     983             :             {
     984           0 :                 ph2_q[i] = 0;
     985           0 :                 ind2[i] = 0;
     986             :             }
     987             :             else
     988             :             {
     989           0 :                 ph2_q[i] = EVS_PI;
     990           0 :                 ind2[i] = n2[i] - 1;
     991             :             }
     992             : 
     993           0 :             sp2cart( ph1_q[i], ph2_q[i], 0, &q_cand[4 * i] );
     994             :         }
     995             : 
     996           0 :         j = sel_q( q, q_cand, 2 );
     997             : 
     998           0 :         mvr2r( q_cand + 4 * j, q, 4 );
     999           0 :         index1 = ind1[j];
    1000           0 :         index2 = ind2[j];
    1001             : 
    1002           0 :         index2 += get_pca_offset_n2( index1 );
    1003             : 
    1004           0 :         *index = ivas_pca_offset_index1[index1] + ivas_pca_offset_index2[index2];
    1005             : 
    1006           0 :         return;
    1007             :     }
    1008             : 
    1009        2232 :     for ( i = 0; i < 2; i++ )
    1010             :     {
    1011        1488 :         n2[i] = calc_n2( ph1_q[i] );
    1012        1488 :         q_ang_2surv( ph2, n2[i], ph2_q + 2 * i, ind2 + 2 * i );
    1013             :     }
    1014         744 :     r = sqrtf( q[2] * q[2] + q[3] * q[3] );
    1015         744 :     v = q[2] / r;
    1016         744 :     ph3 = acos_clip( v );
    1017             : 
    1018         744 :     if ( q[3] < 0 )
    1019             :     {
    1020         373 :         ph3 = PI2 - ph3;
    1021             :     }
    1022             : 
    1023        3720 :     for ( i = 0; i < 4; i++ )
    1024             :     {
    1025        2976 :         n3[i] = calc_n3( ph1_q[i >> 1], ph2_q[i] );
    1026        2976 :         q_ang_circ( ph3, n3[i], ph3_q + i, ind3 + i );
    1027        2976 :         sp2cart( ph1_q[i >> 1], ph2_q[i], ph3_q[i], q_cand + ( 4 * i ) );
    1028             :     }
    1029             : 
    1030         744 :     j = sel_q( q, q_cand, 4 );
    1031             : 
    1032         744 :     mvr2r( q_cand + 4 * j, q, 4 );
    1033             : 
    1034         744 :     index1 = ind1[j >> 1];
    1035         744 :     index2 = ind2[j];
    1036         744 :     index3 = ind3[j];
    1037         744 :     index2 += get_pca_offset_n2( index1 );
    1038             : 
    1039         744 :     *index = ivas_pca_offset_index1[index1] + ivas_pca_offset_index2[index2] + index3;
    1040             : 
    1041         744 :     return;
    1042             : }
    1043             : 
    1044             : /*---------------------------------------------------------------------*
    1045             :  * pca_dec_s3()
    1046             :  *
    1047             :  *
    1048             :  *---------------------------------------------------------------------*/
    1049             : 
    1050        1832 : void pca_dec_s3(
    1051             :     const int32_t index,
    1052             :     float *q )
    1053             : {
    1054             :     float ph1_q, ph2_q, ph3_q;
    1055             :     int32_t j;
    1056             :     int16_t i;
    1057             :     int16_t n1, n2, n3;
    1058             :     int16_t index1, index2, index3;
    1059             :     float d;
    1060             : 
    1061        1832 :     j = index;
    1062        1832 :     index1 = -1;
    1063       28525 :     for ( i = 0; i < IVAS_PCA_N1; i++ )
    1064             :     {
    1065       28525 :         if ( j < ivas_pca_offset_index1[i + 1] )
    1066             :         {
    1067        1832 :             index1 = i;
    1068        1832 :             break;
    1069             :         }
    1070             :     }
    1071             : 
    1072        1832 :     assert( index1 > -1 );
    1073             : 
    1074        1832 :     n1 = IVAS_PCA_N1;
    1075        1832 :     d = EVS_PI / ( n1 - 1 );
    1076        1832 :     ph1_q = index1 * d;
    1077        1832 :     n2 = calc_n2( ph1_q );
    1078             : 
    1079        1832 :     j -= ivas_pca_offset_index1[index1];
    1080        1832 :     index2 = -1;
    1081             : 
    1082       41605 :     for ( i = 0; i < n2; i++ )
    1083             :     {
    1084       41605 :         if ( j < ivas_pca_offset_index2[i + get_pca_offset_n2( index1 ) + 1] )
    1085             :         {
    1086        1832 :             index2 = i;
    1087        1832 :             break;
    1088             :         }
    1089             :     }
    1090             : 
    1091        1832 :     assert( index2 > -1 );
    1092             : 
    1093        1832 :     if ( n2 == 1 )
    1094             :     {
    1095           0 :         ph2_q = 0;
    1096             :     }
    1097             :     else
    1098             :     {
    1099        1832 :         d = EVS_PI / ( n2 - 1 );
    1100        1832 :         ph2_q = index2 * d;
    1101             :     }
    1102             : 
    1103        1832 :     j -= ivas_pca_offset_index2[index2 + get_pca_offset_n2( index1 )];
    1104             : 
    1105        1832 :     index3 = (int16_t) j;
    1106             : 
    1107        1832 :     n3 = calc_n3( ph1_q, ph2_q );
    1108             : 
    1109        1832 :     if ( n3 == 1 )
    1110             :     {
    1111           0 :         ph3_q = 0;
    1112             :     }
    1113             :     else
    1114             :     {
    1115        1832 :         d = PI2 / n3;
    1116        1832 :         ph3_q = d * index3;
    1117             :     }
    1118        1832 :     sp2cart( ph1_q, ph2_q, ph3_q, q );
    1119             : 
    1120        1832 :     return;
    1121             : }

Generated by: LCOV version 1.14