LCOV - code coverage report
Current view: top level - lib_com - index_pvq_opt.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 8834b716eb6d7dfb881d5c69dd21cb18e1692722 Lines: 309 328 94.2 %
Date: 2025-07-09 08:36:12 Functions: 34 34 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             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #ifdef DEBUGGING
      41             : #include "debug.h"
      42             : #endif
      43             : #include <math.h>
      44             : #include "cnst.h"
      45             : #include "rom_com.h"
      46             : #include "prot.h"
      47             : #include "wmc_auto.h"
      48             : 
      49             : /*-------------------------------------------------------------------*
      50             :  *  LOCAL DEFINITIONS
      51             :  *-------------------------------------------------------------------*/
      52             : 
      53             : #define N_OPT         5  /* complexity setting,  direct functional calculation  limit              */
      54             : #define TABLE_LIM_OPT 96 /* odd divisor table recursion limit setting,  due to dim 6               */
      55             : 
      56             : /* local typedefs for optimized pvq indexing, used only in this c-file to vectorize common function calls for c-code clarity */
      57             : typedef void ( *VEC2INDFUNCM )( const int16_t *, int16_t *, uint32_t *, uint32_t * );
      58             : typedef uint32_t ( *NFUNCM )( int16_t );
      59             : typedef uint32_t ( *H_FUNCM )( uint32_t );
      60             : typedef void ( *IND2VECFUNCM )( int16_t, int16_t, uint32_t, int16_t * );
      61             : typedef void ( *NDIM_FUNCM )( int16_t, int16_t, uint32_t, int16_t * );
      62             : 
      63             : /* local constants for indexing functions  c-code clarity */
      64             : #ifndef ONE_U
      65             : 
      66             : #define ZERO    0
      67             : #define ONE     1
      68             : #define ONE_U   1u
      69             : #define TWO     2
      70             : #define SIGNBIT 0x80000000u
      71             : 
      72             : #define MAXBIT 0x40000000L /* if Word32 */
      73             : #define MINNEG 0xffffffffL
      74             : 
      75             : #define UDIVBY3 2863311531U
      76             : 
      77             : 
      78             : /*-------------------------------------------------------------------*
      79             :  *  local_norm_l_opt
      80             :  *
      81             :  *  rewritten version of STL norm_l for integer fixed point normalization
      82             :  *  in floating point c-code.
      83             :  *-------------------------------------------------------------------*/
      84             : 
      85             : /*! r: shifts needed for normalization */
      86     2834943 : static int16_t local_norm_l_opt(
      87             :     int32_t l32var /* i/o: signed 32-bit input value */
      88             : )
      89             : {
      90             :     int16_t l32res;
      91             : 
      92             : #define WMC_TOOL_SKIP
      93             : 
      94     2834943 :     if ( l32var == (int32_t) MINNEG )
      95             :     {
      96           0 :         return ( 32 - ONE );
      97             :     }
      98             :     else
      99             :     {
     100     2834943 :         if ( l32var == ZERO )
     101             :         {
     102           0 :             return ZERO;
     103             :         }
     104             :         else
     105             :         {
     106     2834943 :             if ( l32var < ZERO )
     107             :             {
     108           0 :                 l32var = ~l32var;
     109             :             }
     110             : 
     111    83415966 :             for ( l32res = ZERO; l32var < (int32_t) MAXBIT; l32res++ )
     112             :             {
     113    80581023 :                 l32var <<= ONE;
     114             :             }
     115             :         }
     116             :     }
     117             : #undef WMC_TOOL_SKIP
     118             : 
     119     2834943 :     return ( l32res );
     120             : }
     121             : 
     122             : 
     123             : /*-------------------------------------------------------------------*
     124             :  * floor_sqrt_exact()
     125             :  *   returns  x = floor(sqrt(input));     where (x*x) <= input
     126             :  *-------------------------------------------------------------------*/
     127             : 
     128             : /*! r: floor(sqrt(input)) */
     129      126675 : uint32_t floor_sqrt_exact(
     130             :     const uint32_t input /* i  : unsigned input  [0.. UINT_MAX/4]     */
     131             : )
     132             : {
     133             :     double _tmp;
     134             :     uint32_t x;
     135      126675 :     if ( input == ZERO )
     136             :     {
     137           0 :         return ZERO;
     138             :     }
     139             : 
     140      126675 :     _tmp = (double) input;
     141      126675 :     x = (uint32_t) ( sqrt( _tmp ) ); /* floor is a part of the cast  */
     142             : 
     143      126675 :     return x;
     144             : }
     145             : 
     146             : /*-------------------------------------------------------------------*
     147             :  * f_odd_exact_div_opt()
     148             :  *
     149             :  * find   1/(den1*2+1) * ( num1p*num2p - num3) ,
     150             :  *        if the result is known a priori to be exactly a 32bit unsigned integer
     151             :  *-------------------------------------------------------------------*/
     152             : 
     153             : /*! r: see Eq. */
     154     2560857 : static uint32_t f_odd_exact_div_opt(
     155             :     const int16_t num1p,  /* i  :  see Eq.        */
     156             :     const uint32_t num2p, /* i  :  see Eq.        */
     157             :     const uint32_t num3,  /* i  :  see Eq.        */
     158             :     const int16_t den1    /* i  :  see Eq.        */
     159             : )
     160             : {
     161             :     uint32_t tmp;
     162     2560857 :     tmp = exactdivodd[den1] * ( num1p * num2p - num3 );
     163             : 
     164     2560857 :     return ( tmp );
     165             : }
     166             : 
     167             : /*---------------------------------------------------------------------------*
     168             :  * f_even_exact_div_opt()
     169             :  *
     170             :  *    returns  (num1p*num2p - num3 )/ den1
     171             :  *     if the result is known a priori to be exactly a 32bit unsigned integer
     172             :  *--------------------------------------------------------------------------*/
     173             : 
     174             : /*! r: see Eq. */
     175     2834943 : static uint32_t f_even_exact_div_opt(
     176             :     const int16_t num1p,  /* i  :  see Eq.                                    */
     177             :     const uint32_t num2p, /* i  :  see Eq.  range should be larger than num1p */
     178             :     const uint32_t num3,  /* i  :  see Eq.                                    */
     179             :     const int16_t den1    /* i  :  see Eq.                                    */
     180             : )
     181             : {
     182             :     uint32_t tmp1, oddfactor, UL_tmp;
     183             :     int16_t den1_m1;
     184             :     int16_t even_sh;
     185             :     uint32_t UL_tmp_h;
     186             :     uint64_t ULL_tmp;
     187             : 
     188     2834943 :     den1_m1 = den1 - ONE;                                      /* remove top bit */
     189     2834943 :     even_sh = ( 31 ) - local_norm_l_opt( ( den1_m1 ) ^ den1 ); /*  NB STL operation defined for signed positive 32 bit variable  */
     190     2834943 :     oddfactor = exactdivodd[den1_m1 >> even_sh];
     191     2834943 :     even_sh -= ONE;
     192             : 
     193     2834943 :     ULL_tmp = (uint64_t) num1p * (uint64_t) num2p; /* use STL Mpy_32_32_uu functionality */
     194     2834943 :     UL_tmp_h = (uint32_t) ( ULL_tmp >> 32 );       /* high output from basicop */
     195     2834943 :     UL_tmp = (uint32_t) ( ULL_tmp );               /* low output  from basicop */
     196             : 
     197     2834943 :     if ( num3 > UL_tmp )
     198             :     {
     199         348 :         UL_tmp_h = UL_tmp_h - ONE_U;
     200             :     }
     201     2834943 :     UL_tmp = ( UL_tmp - num3 );                                        /* can and should underflow */
     202     2834943 :     UL_tmp = ( UL_tmp_h << ( 32 - even_sh ) ) | ( UL_tmp >> even_sh ); /* bitwise OR */
     203             : 
     204             :     /* use tabled modular multiplicative inverse for the odd part division */
     205     2834943 :     tmp1 = UL_tmp * oddfactor;
     206             : 
     207     2834943 :     return tmp1;
     208             : }
     209             : 
     210             : /*-------------------------------------------------------------------*
     211             :  * a_three()
     212             :  *-------------------------------------------------------------------*/
     213             : 
     214             : /*! r: offset for dim 3 */
     215       43122 : static uint32_t a_three(
     216             :     const uint32_t k_val /* i  : nb unit pulses; k_val may be higher than  16 bit signed  */
     217             : )
     218             : {
     219       43122 :     if ( k_val )
     220             :     {
     221       42897 :         return ( ONE_U + k_val * ( ( k_val - ONE_U ) << ONE ) );
     222             :     }
     223             :     else
     224             :     {
     225         225 :         return ZERO;
     226             :     }
     227             : }
     228             : 
     229             : /*-------------------------------------------------------------------*
     230             :  * a_four()
     231             :  *-------------------------------------------------------------------*/
     232             : 
     233             : /*! r: offset for dim 4 */
     234      208408 : static uint32_t a_four(
     235             :     const uint32_t k_val /* i  : nb unit pulses   */
     236             : )
     237             : {
     238      208408 :     if ( k_val )
     239             :     {
     240      207974 :         return UDIVBY3 * ( ( k_val << ONE ) * ( 4 + ( ( k_val << ONE ) - 3 ) * k_val ) - 3 );
     241             :     }
     242             : 
     243         434 :     return ZERO;
     244             : }
     245             : 
     246             : /*-------------------------------------------------------------------*
     247             :  * a_five()
     248             :  *-------------------------------------------------------------------*/
     249             : 
     250             : /*! r: offset for dim 5 */
     251        6104 : static uint32_t a_five(
     252             :     const uint32_t k_val /* i  : nb unit pulses   */
     253             : )
     254             : {
     255             :     uint32_t offset;
     256             : 
     257        6104 :     if ( k_val == 0 )
     258             :     {
     259          46 :         offset = 0;
     260             :     }
     261        6058 :     else if ( k_val == 1 )
     262             :     {
     263         100 :         offset = 1;
     264             :     }
     265             :     else
     266             :     {
     267        5958 :         offset = ( ONE_U + ( ( ( ( ( ( k_val - TWO ) * k_val + 5 ) * k_val - 4 ) * k_val ) * ( UDIVBY3 ) ) << ONE ) );
     268             :     }
     269        6104 :     return offset;
     270             : }
     271             : 
     272             : /*-------------------------------------------------------------------*
     273             :  * direct_msize()
     274             :  *-------------------------------------------------------------------*/
     275             : /*! r: Enumeration size */
     276       44366 : static uint32_t direct_msize(
     277             :     const int16_t dim_in, /* i  : Number of dimensions */
     278             :     const int16_t k_in )  /* i  : Number of pulses     */
     279             : {
     280             :     uint32_t msize, k, ksq;
     281             : 
     282       44366 :     msize = ONE_U; /* k==0 or dim==1, and base */
     283       44366 :     if ( k_in )
     284             :     {
     285       44366 :         k = (uint32_t) k_in;
     286       44366 :         ksq = k * k;
     287       44366 :         switch ( dim_in )
     288             :         {
     289        1412 :             case ( 5 ):
     290             :                 /* k*k = 238*238 < 2^16  */
     291        1412 :                 msize += ( ( ( ksq * ( 5 + ksq ) ) * UDIVBY3 ) << ONE );
     292        1412 :                 break;
     293       42350 :             case ( 4 ):
     294       42350 :                 msize = ( ( k * ( ksq + 2 ) ) * UDIVBY3 ) << TWO;
     295       42350 :                 break;
     296          32 :             case ( 3 ):
     297          32 :                 msize += ( ( ksq ) << ONE );
     298          32 :                 break;
     299         404 :             case ( 2 ):
     300         404 :                 msize = k << ONE;
     301         404 :                 break;
     302             :         }
     303           0 :     }
     304             : 
     305       44366 :     return msize;
     306             : }
     307             : 
     308             : 
     309             : /*-------------------------------------------------------------------*
     310             :  * initOffsets()
     311             :  *
     312             :  * update h_mem[0.. k_val_in+1] ,  with starting offsets for A+U recursion
     313             :  *-------------------------------------------------------------------*/
     314             : 
     315      288596 : static void initOffsets(
     316             :     const int16_t dim_in,  /* i  : Number of dimensions */
     317             :     uint32_t *h_mem,       /* o  : offsets              */
     318             :     const int16_t k_val_in /* i  : Number of pulses     */
     319             : )
     320             : {
     321             :     int16_t k_val_curr, k_val_prev;
     322             :     int16_t k_val;
     323      288596 :     h_mem[0] = ZERO;  /*    % A(=>0,k=0)      */
     324      288596 :     h_mem[1] = ONE_U; /*    % A(*,k=1)        */
     325             : 
     326      288596 :     if ( dim_in == 2 )
     327             :     {
     328           0 :         for ( k_val = TWO; k_val <= k_val_in; k_val++ )
     329             :         {
     330           0 :             h_mem[k_val] = (uint32_t) ( ( k_val << ONE ) - ONE ); /* A(2, 2 .. k ) */
     331             :         }
     332           0 :         h_mem[k_val] = (uint32_t) ( k_val_in ); /* U(2,k+1) */
     333             :     }
     334      288596 :     else if ( dim_in == 3 )
     335             :     {
     336      288596 :         k_val_prev = ONE;
     337     2078791 :         for ( k_val_curr = TWO; k_val_curr <= k_val_in; k_val_curr++ )
     338             :         {
     339     1790195 :             h_mem[k_val_curr] = ( ONE_U + k_val_curr * ( k_val_prev << ONE ) );
     340     1790195 :             k_val_prev = k_val_curr;
     341             :         }
     342      288596 :         h_mem[k_val_curr] = k_val_curr * k_val_prev;
     343             :     }
     344           0 :     else if ( dim_in == 4 )
     345             :     {
     346           0 :         for ( k_val_curr = TWO; k_val_curr <= k_val_in; k_val_curr++ )
     347             :         {
     348           0 :             h_mem[k_val_curr] = UDIVBY3 * ( ( k_val_curr << ONE ) * ( 4 + ( ( k_val_curr << ONE ) - 3 ) * k_val_curr ) - 3 );
     349             :         }
     350           0 :         h_mem[k_val_curr] = ( UDIVBY3 * ( ( k_val_curr << ONE ) * ( 4 + ( ( k_val_curr << ONE ) - 3 ) * k_val_curr ) - 3 ) ) >> 1;
     351             :     }
     352             : 
     353      288596 :     return;
     354             : }
     355             : 
     356             : 
     357             : /*-------------------------------------------------------------------*
     358             :  * a_fwd()
     359             :  *
     360             :  *  create offsets for A(n,k)  from lower A(n-1,k)
     361             :  *-------------------------------------------------------------------*/
     362             : 
     363     2923872 : static void a_fwd(
     364             :     uint32_t *a_in,       /* i/o: offsets         */
     365             :     const int16_t n_items /* i  :  items, k's     */
     366             : )
     367             : {
     368             :     uint32_t a_1;
     369             :     int16_t i, i_prev;
     370             :     uint32_t a_in0; /* i  :  start column value   */
     371             : 
     372     2923872 :     a_in0 = ONE_U;
     373     2923872 :     i_prev = ZERO;
     374    20600972 :     for ( i = ONE; i <= n_items; i++ ) /*basic A   fwd row  recursion */
     375             :     {
     376    17677100 :         a_1 = a_in0 + a_in[i_prev] + a_in[i]; /* a_in addressed in at least two locations */
     377    17677100 :         a_in[i_prev] = a_in0;
     378    17677100 :         a_in0 = a_1;
     379    17677100 :         i_prev = i; /* no real need to count as it is a ptr update */
     380             :     }
     381     2923872 :     a_in[i_prev] = a_in0;
     382             : 
     383     2923872 :     return;
     384             : }
     385             : 
     386             : /*-------------------------------------------------------------------*
     387             :  * a_bwd()
     388             :  *
     389             :  * create offsets for A(n,k)  from higher A(n+1,k)
     390             :  *-------------------------------------------------------------------*/
     391             : 
     392     8044077 : static void a_bwd(
     393             :     uint32_t *a_in,       /* i/o: offsets     */
     394             :     const int16_t n_items /* i  : n_items     */
     395             : )
     396             : {
     397             :     uint32_t a_1;
     398             :     uint32_t a_in0;
     399             :     int16_t i;
     400             :     int16_t i_prev;
     401             : 
     402     8044077 :     a_in0 = ZERO;
     403     8044077 :     i_prev = ZERO;
     404    48383283 :     for ( i = ONE; i <= n_items; i++ ) /*basic A   reverse row  recursion */
     405             :     {
     406    40339206 :         a_1 = a_in[i] - a_in0 - a_in[i_prev];
     407    40339206 :         a_in[i_prev] = a_in0;
     408    40339206 :         a_in0 = a_1;
     409    40339206 :         i_prev = i;
     410             :     }
     411     8044077 :     a_in[i_prev] = a_in0;
     412             : 
     413     8044077 :     return;
     414             : }
     415             : 
     416             : /*-------------------------------------------------------------------*
     417             :  * direct_row_A2U_rec_calc()
     418             :  *
     419             :  *
     420             :  *-------------------------------------------------------------------*/
     421             : 
     422      852288 : static uint32_t direct_row_A2U_rec_calc(
     423             :     const int16_t dim_in,   /* i  : Number of dimensions             */
     424             :     const int16_t k_val_in, /* i  : Number of pulses                 */
     425             :     const uint32_t a_km2,   /* i  : Recursion for k-2 (see Eq below) */
     426             :     const uint32_t a_km1    /* i  : Recursion for k-1 (see Eq below) */
     427             : )
     428             : {
     429             : 
     430             :     /*  U(n,k)    =  (A(n,k-2)-1)/2     +     ((2*n-1)*A(n,k-1) - A(n,k-2) )/2*(k-1)           */
     431             :     /*  U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - floor(A(n,k-1)/2) - floor(A(n,k-2)/2) +1 )/(k-1) */
     432             :     /*  U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - (floor(A(n,k-1)/2) + floor(A(n,k-2)/2) +1) ) /(k-1) */
     433             : 
     434             :     uint32_t km2_size, result;
     435             :     int16_t divisor;
     436             : 
     437      852288 :     divisor = k_val_in - ONE;
     438      852288 :     km2_size = ( a_km1 >> ONE ) + ( a_km2 >> ONE ) + ONE_U;
     439             : 
     440      852288 :     if ( divisor & ONE )
     441             :     {
     442             :         /* odd */
     443      473550 :         result = ( ( a_km2 >> ONE ) + f_odd_exact_div_opt( dim_in, a_km1, km2_size, divisor >> ONE ) );
     444             :     }
     445             :     else
     446             :     {
     447             :         /* even divisor */
     448      378738 :         result = ( ( a_km2 >> ONE ) + f_even_exact_div_opt( dim_in, a_km1, km2_size, divisor ) );
     449             :     }
     450             : 
     451      852288 :     return result;
     452             : }
     453             : 
     454             : /*-------------------------------------------------------------------*
     455             :  * a_u_fwd()
     456             :  *
     457             :  *
     458             :  *-------------------------------------------------------------------*/
     459             : 
     460     2923872 : static void a_u_fwd(
     461             :     uint32_t *a_u_in,         /* o  : auxiliary array a_u */
     462             :     const int16_t k_val_in,   /* i  : number of pulses    */
     463             :     const int16_t mem_size_m1 /* i  : length of a_u_in    */
     464             : )
     465             : {
     466             :     uint32_t u_kp1_prev;
     467             :     uint32_t a_k_prev;
     468             : 
     469             :     /* mem_size_m1 =  1 + k_val_in   */
     470     2923872 :     u_kp1_prev = a_u_in[mem_size_m1]; /* previous  n  U (n,k+1) value*/
     471     2923872 :     a_k_prev = a_u_in[k_val_in];      /* previous  n  A(n,k) value*/
     472             : 
     473     2923872 :     a_fwd( &a_u_in[ONE], k_val_in ); /* a_u_in[k==ZERO] = zero if n>0 */
     474             : 
     475             :     /*      low dynamic last offset entry mixed recursion */
     476             :     /*      used for size calculation  */
     477             :     /*      U(n,k+1) = 1 + U(n-1,k+1) + U(n-1,k)        + U(n,k)                            */
     478             :     /*      U(n,k+1) = 1 + U(n-1,k+1) + (A(n-1,k)-1)/2  + (A(n,k)-1)/2                      */
     479             :     /*                  Note, A(n,k) always odd for k>0, subtracted one always shifted out  */
     480             :     /*                  assert(a_k_prev>0, a_k-curr>0)                                      */
     481             : 
     482     2923872 :     a_u_in[mem_size_m1] = ONE_U + u_kp1_prev + ( a_k_prev >> ONE ) + ( a_u_in[k_val_in] >> ONE );
     483             : 
     484     2923872 :     return;
     485             : }
     486             : 
     487             : /*-------------------------------------------------------------------*
     488             :  * nm_h_prep_opt()
     489             :  *
     490             :  * find  and return  N_MPVQ(n,k) and also offsets A(n, 0  to  k ) and  U(n,k+1).
     491             :  *-------------------------------------------------------------------*/
     492             : 
     493             : /*! r: msize for dim */
     494      852288 : static uint32_t nm_h_prep_opt(
     495             :     const int16_t dim_in, /* i  :  dimension         */
     496             :     int16_t k_val_in,     /* i  :  nb unit pulses    */
     497             :     uint32_t *h           /* o  :  A/U offsets array */
     498             : )
     499             : {
     500             :     int16_t mem_size_m1, k_val;
     501             :     int16_t dim_tmp, d_start;
     502             :     uint32_t h_saveA, h_saveB; /*  registers   for alternating  A(n,k-1), A(n,k-2)*/
     503             :     int16_t numDsub1;          /*  k_val_curr, k_val_prev*/
     504             : 
     505      852288 :     mem_size_m1 = k_val_in + ONE;
     506             : 
     507      852288 :     if ( k_val_in > TABLE_LIM_OPT )
     508             :     {
     509           0 :         if ( dim_in >= 3 )
     510             :         {
     511           0 :             d_start = 3;
     512             :         }
     513             :         else
     514             :         {
     515           0 :             d_start = 2;
     516             :         }
     517           0 :         initOffsets( d_start, h, k_val_in );
     518             : 
     519           0 :         for ( dim_tmp = d_start; dim_tmp < dim_in; dim_tmp++ )
     520             :         {
     521           0 :             a_u_fwd( h, k_val_in, mem_size_m1 );
     522             :         }
     523             :     }
     524             :     else
     525             :     {
     526      852288 :         h[ZERO] = ZERO;
     527      852288 :         h[ONE] = ONE_U;
     528      852288 :         numDsub1 = ( ( dim_in << ONE ) - ONE );
     529      852288 :         h[TWO] = numDsub1;
     530             : 
     531             :         /* interleaved odd even calls */
     532      852288 :         h_saveA = numDsub1;
     533      852288 :         h_saveB = ONE_U;
     534     2939595 :         for ( k_val = 3; k_val < ( mem_size_m1 ); k_val++ )
     535             :         {
     536             :             /* A(n,k)  =  A(n,k-2) + ((2*n-1)*A(n,k-1)-A(n,k-2)) /(k-1)  */
     537             :             /* first odd  k, even divisor */
     538     2456205 :             h_saveB += f_even_exact_div_opt( numDsub1, h_saveA, h_saveB, k_val - ONE );
     539     2456205 :             h[k_val] = h_saveB;
     540             : 
     541     2456205 :             k_val++; /* next even k, odd divisor */
     542     2456205 :             if ( k_val >= ( mem_size_m1 ) )
     543             :             {
     544      368898 :                 break;
     545             :             }
     546     2087307 :             h_saveA += f_odd_exact_div_opt( numDsub1, h_saveB, h_saveA, ( k_val - ONE ) >> ONE );
     547     2087307 :             h[k_val] = h_saveA;
     548             :         }
     549             :         /*  always do the last (k+1) recursion based  on  U(n,k+1) = func( A(n-2,k+1), A(n-1,k+1) )   */
     550      852288 :         h[mem_size_m1] = direct_row_A2U_rec_calc( dim_in, mem_size_m1, h[mem_size_m1 - 2], h[k_val_in] );
     551             :     }
     552             : 
     553             :     /*  N_MPVQ(n,k) = 1 + U(n,k+1) + U(n,k) =  1 + U(n,k+1) + (A(n,k)-1)/2;   */ /* A(n,k) always odd */
     554      852288 :     return ( ONE + h[mem_size_m1] + ( h[k_val_in] >> ONE ) );
     555             : }
     556             : 
     557             : 
     558             : /*-------------------------------------------------------------------*
     559             :  * find_amp_split_offset_func_mem()
     560             :  *
     561             :  * find first offset  in range 0..k_val_in  that is less than ind_in
     562             :  * using a tree search with direct function calls or memory iteration
     563             :  *-------------------------------------------------------------------*/
     564             : 
     565       33657 : static int16_t find_amp_split_offset_func_mem(
     566             :     const uint32_t ind_in,       /* i  : input index             */
     567             :     const int16_t k_val_in,      /* i  : number of pulses        */
     568             :     H_FUNCM h_func_ptr,          /* i  : offset function pointer */
     569             :     const uint32_t *const h_mem, /* i  : offsets                 */
     570             :     uint32_t *tmp_offset         /* o  : offset found            */
     571             : )
     572             : {
     573             :     int16_t not_ready, low, high;
     574             :     int16_t k_test;
     575             : 
     576       33657 :     k_test = -1; /* init to eliminate compiler warning */
     577       33657 :     low = 0;
     578       33657 :     high = k_val_in;
     579             :     /* split over  A(n,k)= h_mem(k), or use direct function  */
     580       33657 :     not_ready = ONE;
     581      236796 :     while ( not_ready )
     582             :     {
     583      203139 :         k_test = ( low + high ) >> ONE; /*% split range in half */
     584             : 
     585      203139 :         if ( h_mem )
     586             :         {
     587           0 :             *tmp_offset = h_mem[k_test]; /* memory search  */
     588             :         }
     589             :         else
     590             :         {
     591      203139 :             *tmp_offset = ( *h_func_ptr )( (uint32_t) k_test ); /* function search. NB only line difference to the memory search*/
     592             :         }
     593             : 
     594      203139 :         if ( ind_in > *tmp_offset )
     595             :         {
     596      141831 :             if ( k_test < high )
     597             :             {
     598      108495 :                 low = 1 + k_test;
     599             :             }
     600             :             else
     601             :             {
     602       33336 :                 not_ready = 0;
     603             :             }
     604             :         }
     605             :         else
     606             :         {
     607       61308 :             if ( *tmp_offset == ind_in )
     608             :             {
     609         321 :                 not_ready = 0;
     610             :             }
     611             :             else
     612             :             {
     613       60987 :                 high = k_test - 1;
     614             :             }
     615             :         }
     616             :     }
     617             : 
     618       33657 :     return k_test;
     619             : }
     620             : 
     621             : /*-------------------------------------------------------------------*
     622             :  * get_lead_sign()
     623             :  *
     624             :  * update  index and return leading sign
     625             :  *-------------------------------------------------------------------*/
     626             : 
     627             : /*! r: leading sign [-1,1] */
     628     2835990 : static int16_t get_lead_sign(
     629             :     uint32_t *ind /* i/o: Current index                 */
     630             : )
     631             : {
     632             :     int16_t leading_sign;
     633             : 
     634     2835990 :     if ( ( *ind ) & ONE_U ) /*  leading sign stored in LSB  */
     635             :     {
     636     1416423 :         leading_sign = -1;
     637             :     }
     638             :     else
     639             :     {
     640     1419567 :         leading_sign = 1;
     641             :     }
     642     2835990 :     ( *ind ) = ( *ind ) >> ONE;
     643             : 
     644     2835990 :     return leading_sign;
     645             : }
     646             : 
     647             : 
     648             : /*-------------------------------------------------------------------*
     649             :  * mind2vec_one()
     650             :  *-------------------------------------------------------------------*/
     651             : 
     652         126 : static void mind2vec_one(
     653             :     const int16_t k_val_in,     /* i  : nb unit pulses   */
     654             :     const int16_t leading_sign, /* i  : leading sign     */
     655             :     const uint32_t ind,         /* i  : index            */
     656             :     int16_t *vec_out            /* o  : pulse train      */
     657             : )
     658             : {
     659             : 
     660         126 :     vec_out[ind] = ( leading_sign * k_val_in ); /*  NB  input k_val_in can be zero  */
     661             : 
     662         126 :     return;
     663             : }
     664             : 
     665             : /*-------------------------------------------------------------------*
     666             :  * mind2vec_two()
     667             :  *-------------------------------------------------------------------*/
     668             : 
     669       32400 : static void mind2vec_two(
     670             :     const int16_t k_val_in,     /* i  : nb unit pulses   */
     671             :     const int16_t leading_sign, /* i  : leading sign     */
     672             :     const uint32_t ind_in,      /* i  : index            */
     673             :     int16_t *vec_out            /* o  : pulse train      */
     674             : )
     675             : {
     676             :     uint32_t ind_tmp;
     677             :     int16_t val1;
     678             : 
     679       32400 :     if ( k_val_in > 0 ) /* k_val_in check   */
     680             :     {
     681       32400 :         if ( ind_in == 0 )
     682             :         {
     683        2400 :             vec_out[0] = ( leading_sign * k_val_in );
     684        2400 :             vec_out[1] = 0;
     685             :         }
     686       30000 :         else if ( ind_in == ( (uint32_t) ( k_val_in << ONE ) - ONE_U ) )
     687             :         {
     688        1701 :             vec_out[0] = 0;
     689        1701 :             vec_out[1] = ( leading_sign * k_val_in );
     690             :         }
     691             :         else
     692             :         {
     693       28299 :             ind_tmp = ind_in - ONE_U;
     694       28299 :             val1 = (int16_t) ( ONE_U + ( ind_tmp >> ONE ) );
     695       28299 :             vec_out[0] = leading_sign * ( k_val_in - val1 );
     696             : 
     697       28299 :             if ( ind_tmp & ONE_U )
     698             :             {
     699       14511 :                 vec_out[1] = -val1;
     700             :             }
     701             :             else
     702             :             {
     703       13788 :                 vec_out[1] = val1;
     704             :             }
     705             :         }
     706             :     }
     707             : 
     708       32400 :     return;
     709             : }
     710             : 
     711             : /*-------------------------------------------------------------------*
     712             :  * setval_update_sign()
     713             :  *
     714             :  *
     715             :  *-------------------------------------------------------------------*/
     716             : 
     717             : /*! r: max k */
     718     8109831 : static int16_t setval_update_sign(
     719             :     const int16_t k_delta, /* i  : Delta-K                                */
     720             :     int16_t k_max_local,   /* i/o: Maximum K                              */
     721             :     int16_t *leading_sign, /* o  : Leading sign                           */
     722             :     uint32_t *ind_in,      /* i/o: Index/index with leading sign excluded */
     723             :     int16_t *vec_out       /* o  : Output vector                          */
     724             : )
     725             : {
     726     8109831 :     if ( k_delta != 0 )
     727             :     {
     728     2835990 :         *vec_out = ( *leading_sign ) * k_delta;
     729     2835990 :         *leading_sign = get_lead_sign( ind_in );
     730     2835990 :         k_max_local = k_max_local - k_delta;
     731             :     }
     732             : 
     733     8109831 :     return k_max_local;
     734             : }
     735             : 
     736             : /*-------------------------------------------------------------------*
     737             :  * mind2vec_three()
     738             :  *-------------------------------------------------------------------*/
     739             : 
     740       32628 : static void mind2vec_three(
     741             :     int16_t k_max_local,  /* i  : nb unit pulses    */
     742             :     int16_t leading_sign, /* i  : leading sign      */
     743             :     uint32_t ind_in,      /* i  : index             */
     744             :     int16_t *vec_out      /* o  : pulse train       */
     745             : )
     746             : {
     747             :     int16_t k_delta;
     748             :     uint32_t acc_val;
     749             : 
     750             :     /*
     751             :         use direct calculation of first amplitude
     752             :         (to find amplitudes faster than using split or linear iteration)
     753             :     */
     754       32628 :     if ( ind_in == 0 )
     755             :     {
     756         531 :         vec_out[0] = leading_sign * k_max_local;
     757             :     }
     758             :     else
     759             :     {
     760       32097 :         acc_val = ( ( ONE_U + floor_sqrt_exact( ( ind_in << ONE ) - ONE_U ) ) >> ONE ); /* in BASOP use approximation + search for exact sqrt )*/
     761             : 
     762       32097 :         k_delta = k_max_local - (int16_t) acc_val;
     763       32097 :         ind_in -= a_three( acc_val ); /* remove amplitude offset A(n,k_acc) */
     764             : 
     765       32097 :         k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind_in, vec_out );
     766             : 
     767       32097 :         mind2vec_two( k_max_local, leading_sign, ind_in, &vec_out[1] );
     768             :     }
     769             : 
     770       32628 :     return;
     771             : }
     772             : 
     773             : /*-------------------------------------------------------------------*
     774             :  * mind2vec_direct()
     775             :  *
     776             :  * general function for direct decoding using direct functions
     777             :  * (no  memory recursion)
     778             :  *-------------------------------------------------------------------*/
     779             : 
     780       33798 : static void mind2vec_direct(
     781             :     int16_t k_max_local,    /* i  : nb unit pulses           */
     782             :     int16_t leading_sign,   /* i  : leading sign             */
     783             :     uint32_t ind,           /* i  : index                    */
     784             :     H_FUNCM h_func_ptr,     /* i  : offset function          */
     785             :     NDIM_FUNCM nd_func_ptr, /* i  : next dimension function  */
     786             :     int16_t *vec_out        /* o  : pulse train              */
     787             : )
     788             : {
     789       33798 :     int16_t k_delta, k_test = 0;
     790             :     uint32_t tmp_offset;
     791             : 
     792       33798 :     if ( ind == 0 )
     793             :     {
     794         141 :         vec_out[0] = leading_sign * k_max_local;
     795             :     }
     796             :     else
     797             :     {
     798       33657 :         k_test = find_amp_split_offset_func_mem( ind, k_max_local, h_func_ptr, NULL, &tmp_offset );
     799             : 
     800       33657 :         k_delta = k_max_local - k_test;
     801       33657 :         ind = ind - tmp_offset; /* %  remove amplitude offset A(n,k_acc) */
     802       33657 :         k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, vec_out );
     803       33657 :         ( *nd_func_ptr )( k_max_local, leading_sign, ind, &vec_out[1] );
     804             :     }
     805             : 
     806       33798 :     return;
     807             : }
     808             : 
     809             : /*-------------------------------------------------------------------*
     810             :  * mind2vec_four()
     811             :  *-------------------------------------------------------------------*/
     812             : 
     813       32742 : static void mind2vec_four(
     814             :     int16_t k_val_in,     /* i  : nb unit pulses    */
     815             :     int16_t leading_sign, /* i  : leading sign      */
     816             :     uint32_t ind_in,      /* i  : index             */
     817             :     int16_t *vec_out      /* o  : pulse train       */
     818             : )
     819             : {
     820       32742 :     mind2vec_direct( k_val_in, leading_sign, ind_in, a_four, mind2vec_three, vec_out );
     821             : 
     822       32742 :     return;
     823             : }
     824             : 
     825             : /*-------------------------------------------------------------------*
     826             :  * mind2vec_five()
     827             :  *-------------------------------------------------------------------*/
     828             : 
     829        1056 : static void mind2vec_five(
     830             :     int16_t k_val_in,     /* i  : nb unit pulses   */
     831             :     int16_t leading_sign, /* i  : leading sign     */
     832             :     uint32_t ind_in,      /* i  : index            */
     833             :     int16_t *vec_out      /* o  : pulse train      */
     834             : )
     835             : {
     836        1056 :     mind2vec_direct( k_val_in, leading_sign, ind_in, a_five, mind2vec_four, vec_out );
     837             : 
     838        1056 :     return;
     839             : }
     840             : 
     841             : 
     842             : /*-------------------------------------------------------------------*
     843             :  * mind2vec()
     844             :  *-------------------------------------------------------------------*/
     845             : 
     846      852288 : static void mind2vec(
     847             :     int16_t dim_in,       /* i  : dimension                 */
     848             :     int16_t k_max_local,  /* i  : nb unit pulses            */
     849             :     int16_t leading_sign, /* i  : leading sign              */
     850             :     uint32_t ind,         /* i  : index                     */
     851             :     int16_t *vec_out,     /* o  : pulse train               */
     852             :     uint32_t *h_in        /* i  : offset vector   A=1+2U    */
     853             : )
     854             : {
     855             :     int16_t pos;
     856             :     int16_t k_acc, k_delta;
     857             :     uint32_t tmp_offset;
     858             : 
     859      852288 :     k_acc = k_max_local;
     860             : 
     861      852288 :     pos = ZERO;
     862     8896365 :     while ( pos < dim_in ) /* first to last position decoding */
     863             :     {
     864     8896365 :         if ( ind == 0 )
     865             :         {
     866      852288 :             vec_out[pos] = leading_sign * k_max_local;
     867      852288 :             break; /* "fast" recursion exit */
     868             :         }
     869             :         else
     870             :         {
     871             :             {
     872             :                 /* linear magnitude search */
     873     8044077 :                 k_acc = k_max_local;
     874     8044077 :                 tmp_offset = h_in[k_acc];
     875    12883296 :                 while ( tmp_offset > ind )
     876             :                 {
     877     4839219 :                     k_acc = k_acc - 1;
     878     4839219 :                     tmp_offset = h_in[k_acc];
     879             :                 }
     880             :             }
     881     8044077 :             k_delta = k_max_local - k_acc; /* amplitude decoding */
     882             :         }
     883     8044077 :         ind = ind - tmp_offset; /* remove amplitude index offset A(n,k_acc) */
     884             : 
     885     8044077 :         k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos] );
     886             : 
     887             :         /* move from  A(n,kmax) to A(n-1, k_max_local), */
     888     8044077 :         a_bwd( h_in, k_max_local + 1 ); /* [0..k_max_local], no need to calculate U(n,k_max_local+1) in index decoding   */
     889     8044077 :         pos = pos + 1;
     890             :     }
     891             : 
     892      852288 :     return;
     893             : }
     894             : 
     895             : 
     896             : /*-------------------------------------------------------------------*
     897             :  * vec2mind_one()
     898             :  *-------------------------------------------------------------------*/
     899             : 
     900          42 : static void vec2mind_one(
     901             :     const int16_t *vec_in,   /* i  : PVQ abs pulse train      */
     902             :     int16_t *k_val_out_ptr,  /* o  : number of unit pulses    */
     903             :     uint32_t *next_sign_ind, /* i/o: next sign ind            */
     904             :     uint32_t *ind            /* o  : MPVQ index               */
     905             : )
     906             : {
     907          42 :     *k_val_out_ptr = -1; /* just to avoid compiler warnings */
     908             : 
     909          42 :     *ind = ZERO;
     910             :     /* *k_val_out_ptr =  (int16_t)abs(*vec_in);  */ /* dim==1, function not called recursively */
     911          42 :     *next_sign_ind = (uint32_t) ( *vec_in < ZERO ); /* single sign always pushed out of MPVQ */
     912          42 :     return;
     913             : }
     914             : 
     915             : /*-------------------------------------------------------------------*
     916             :  * vec2mind_two()
     917             :  *-------------------------------------------------------------------*/
     918             : 
     919      299722 : static void vec2mind_two(
     920             :     const int16_t *vec_in,   /* i  : PVQ  pulse train        */
     921             :     int16_t *k_val_out_ptr,  /* o  : number of unit pulses   */
     922             :     uint32_t *next_sign_ind, /* i/o: next sign ind           */
     923             :     uint32_t *ind            /* o  : MPVQ index              */
     924             : )
     925             : {
     926             :     uint32_t lead_sign_ind;
     927             :     int16_t abs0, abs1, abs01;
     928             : 
     929      299722 :     abs0 = (int16_t) abs( vec_in[0] );
     930      299722 :     abs1 = (int16_t) abs( vec_in[1] );
     931             : 
     932      299722 :     abs01 = abs0 + abs1;
     933      299722 :     *k_val_out_ptr = abs01;
     934             : 
     935      299722 :     if ( abs01 == 0 ) /* zeroes  can happen in a recursive encoding call */
     936             :     {
     937      130749 :         *next_sign_ind = SIGNBIT;
     938      130749 :         *ind = ZERO;
     939             :     }
     940             :     else
     941             :     {
     942      168973 :         *next_sign_ind = 0;
     943      168973 :         if ( abs1 == 0 )
     944             :         {
     945       50034 :             *ind = ZERO;
     946             :         }
     947      118939 :         else if ( abs0 == 0 )
     948             :         {
     949       47624 :             *ind = (uint32_t) ( abs1 << ONE ) - ONE_U;
     950       47624 :             *next_sign_ind = 1;
     951             :         }
     952             :         else
     953             :         {
     954       71315 :             lead_sign_ind = (uint32_t) ( vec_in[1] < 0 ); /*% sign always shifted to first pos */
     955       71315 :             *ind = ONE_U + ( (uint32_t) ( abs1 - 1 ) << ONE ) + lead_sign_ind;
     956             :         }
     957      168973 :         *next_sign_ind = (uint32_t) ( vec_in[*next_sign_ind] < 0 );
     958             :     }
     959             : 
     960      299722 :     return;
     961             : }
     962             : 
     963             : 
     964             : /*-------------------------------------------------------------------*
     965             :  *  vec2mind_gen345( vec_in kval,   next_dim_func, offset_func,....)
     966             :  *   generic call saves  PROM ,
     967             :  *-------------------------------------------------------------------*/
     968             : 
     969       22398 : static void vec2mind_gen345(
     970             :     const int16_t *vec_in,        /* i  : PVQ abs pulse train     */
     971             :     int16_t *k_val_out_ptr,       /* o  : number of unit pulses   */
     972             :     uint32_t *next_sign_ind,      /* i/o: next sign ind           */
     973             :     uint32_t *index,              /* o  : MPVQ index              */
     974             :     VEC2INDFUNCM vec2indfunc_ptr, /* i  :                         */
     975             :     H_FUNCM a_func_ptr            /* i  : offset function         */
     976             : )
     977             : {
     978             :     int16_t tmp_val;
     979             : 
     980       22398 :     tmp_val = vec_in[ZERO];
     981       22398 :     ( *vec2indfunc_ptr )( &vec_in[ONE], k_val_out_ptr, next_sign_ind, index );
     982             : 
     983       22398 :     if ( ( ( *next_sign_ind & SIGNBIT ) == 0 && tmp_val != 0 ) != ZERO )
     984             :     {
     985       20263 :         *index = ( *index << ONE ) + *next_sign_ind;
     986             :     }
     987             : 
     988       22398 :     if ( tmp_val != 0 ) /* push sign */
     989             :     {
     990       20488 :         *next_sign_ind = (uint32_t) ( tmp_val < 0 );
     991             :     }
     992             : 
     993       22398 :     *index += ( *a_func_ptr )( (uint32_t) *k_val_out_ptr );
     994       22398 :     if ( tmp_val > 0 )
     995             :     {
     996       10266 :         *k_val_out_ptr += tmp_val;
     997             :     }
     998             :     else
     999             :     {
    1000       12132 :         *k_val_out_ptr -= tmp_val;
    1001             :     }
    1002             : 
    1003       22398 :     return;
    1004             : }
    1005             : 
    1006             : 
    1007             : /*-------------------------------------------------------------------*
    1008             :  * vec2mind_three()
    1009             :  *-------------------------------------------------------------------*/
    1010             : 
    1011       11025 : static void vec2mind_three(
    1012             :     const int16_t *vec_in,   /* i  : PVQ   pulse train       */
    1013             :     int16_t *k_val_out_ptr,  /* o  : number of unit pulses   */
    1014             :     uint32_t *next_sign_ind, /* i/o: next sign ind           */
    1015             :     uint32_t *index          /* o  : MPVQ index              */
    1016             : )
    1017             : {
    1018       11025 :     vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_two, a_three );
    1019             : 
    1020       11025 :     return;
    1021             : }
    1022             : 
    1023             : /*-------------------------------------------------------------------*
    1024             :  * vec2mind_four()
    1025             :  *-------------------------------------------------------------------*/
    1026             : 
    1027       11017 : static void vec2mind_four(
    1028             :     const int16_t *vec_in,   /* i  : PVQ  pulse train        */
    1029             :     int16_t *k_val_out_ptr,  /* o  : number of unit pulses   */
    1030             :     uint32_t *next_sign_ind, /* i/o: next sign ind           */
    1031             :     uint32_t *index          /* o  : MPVQ index              */
    1032             : )
    1033             : {
    1034       11017 :     vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_three, a_four );
    1035             : 
    1036       11017 :     return;
    1037             : }
    1038             : 
    1039             : /*-------------------------------------------------------------------*
    1040             :  * vec2mind_five()
    1041             :  *-------------------------------------------------------------------*/
    1042             : 
    1043         356 : static void vec2mind_five(
    1044             :     const int16_t *vec_in,   /* i  : PVQ abs pulse train     */
    1045             :     int16_t *k_val_out_ptr,  /* o  : number of unit pulses   */
    1046             :     uint32_t *next_sign_ind, /* i/o: next sign ind           */
    1047             :     uint32_t *index          /* o  : MPVQ index              */
    1048             : )
    1049             : {
    1050         356 :     vec2mind_gen345( vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_four, a_five );
    1051             : 
    1052         356 :     return;
    1053             : }
    1054             : 
    1055             : 
    1056             : /*-------------------------------------------------------------------*
    1057             :  * vec2mind()
    1058             :  *-------------------------------------------------------------------*/
    1059             : 
    1060      288596 : static void vec2mind(
    1061             :     int16_t dim_in,          /* i  : dim                       */
    1062             :     int16_t k_val_in,        /* i  : number of unit pulses     */
    1063             :     const int16_t *vec_in,   /* i  : PVQ pulse train           */
    1064             :     uint32_t *next_sign_ind, /* o  : pushed leading sign       */
    1065             :     uint32_t *index,         /* o  : MPVQ index                */
    1066             :     uint32_t *N_MPVQ_ptr,    /* o  : size(N_MPVQ(dim,K_val_in))*/
    1067             :     uint32_t *h_mem          /* o  : offsets                   */
    1068             : )
    1069             : {
    1070             :     int16_t pos, mem_size_m1;
    1071             :     int16_t k_val_acc;
    1072             :     int16_t tmp_val;
    1073             : 
    1074      288596 :     mem_size_m1 = k_val_in + ONE;
    1075             : 
    1076      288596 :     *next_sign_ind = SIGNBIT; /*  % should always be 0 or 1 out,  highest bit set signals no sign found yet*/
    1077             : 
    1078      288596 :     pos = dim_in - 2; /*  % address 2nd last sample */
    1079      288596 :     vec2mind_two( &vec_in[pos], &k_val_acc, next_sign_ind, index );
    1080      288596 :     initOffsets( 3, h_mem, k_val_in );
    1081             : 
    1082     3501064 :     for ( pos--; pos >= 0; pos-- )
    1083             :     {
    1084             :         /*
    1085             :         %   Check if the  leading sign 'bit' is to be added
    1086             :         */
    1087     3212468 :         tmp_val = vec_in[pos];
    1088     3212468 :         if ( ( ( *next_sign_ind & SIGNBIT ) == 0 && ( tmp_val != 0 ) ) )
    1089             :         {
    1090      876055 :             *index = ( *index << ONE ) + ( *next_sign_ind );
    1091             :         }
    1092             : 
    1093             :         /* % push sign fwd,  for encoding in the next non_zero position  */
    1094     3212468 :         if ( tmp_val != 0 )
    1095             :         {
    1096     1006579 :             *next_sign_ind = (uint32_t) ( tmp_val < 0 );
    1097             :         }
    1098             : 
    1099             :         /*%  add  indexing offset up to this reverse (r_l) accumulated  amplitude point */
    1100     3212468 :         *index += h_mem[k_val_acc]; /* % k_val_acc==0 ==>0 */
    1101             : 
    1102     3212468 :         k_val_acc += (int16_t) abs( tmp_val ); /*% now increase acc k value for next N */
    1103             : 
    1104     3212468 :         if ( pos )
    1105             :         {
    1106     2923872 :             a_u_fwd( h_mem, k_val_in, mem_size_m1 );
    1107             :             /*%  update A(n,k=1:k_val_in) and U(n,k_val_in+1), NB here  (k_val_in + 2 elements always has to be updated */
    1108             :         }
    1109             :     }
    1110             : 
    1111             :     /*   size is needed for the subseqent arithmetic encoding/transmission of the index.        */
    1112             :     /* use relation N_MPVQ(n,K) =  1 +  (A(n, K)-1)/2 + U(n, 1 + K)                        */
    1113             :     /* =            N_MPVQ(n,K) =  1 +  (A(n, K)>>1)  + U(n, 1 + K),  as A(n,K) is odd)   */
    1114             : 
    1115      288596 :     *N_MPVQ_ptr = ONE_U + ( h_mem[k_val_acc] >> ONE ) + h_mem[mem_size_m1]; /*  total size size */
    1116             : 
    1117      288596 :     return;
    1118             : }
    1119             : 
    1120             : /*--------------------------------------------------------------------------*
    1121             :  * mpvq_encode_vec()
    1122             :  *
    1123             :  * returns struct with  leading sign index, MPVQ-index,  dim   and  N_MPVQ
    1124             :  *-------------------------------------------------------------------------*/
    1125             : 
    1126             : /*! r: leading_sign_index, index, size, k_val */
    1127      299764 : PvqEntry mpvq_encode_vec(
    1128             :     const int16_t *vec_in, /* i  : signed pulse train                       */
    1129             :     const int16_t dim_in,  /* i  : dimension                                */
    1130             :     int16_t k_val_local    /* i/o: nb unit pulses                           */
    1131             : )
    1132             : {
    1133             :     PvqEntry result;
    1134             :     uint32_t h_mem[1 + KMAX_NON_DIRECT + 1]; /* allocate max offset memory  for dim 6    */ /* OPT: actually only 1+k_val_in+1 needed ) */
    1135             :     uint32_t lead_sign_ind;
    1136      299764 :     const VEC2INDFUNCM vec2mind_f[1 + N_OPT] = { NULL, vec2mind_one, vec2mind_two, vec2mind_three, vec2mind_four, vec2mind_five }; /* VEC2INDFUNCM can be a static global  */
    1137             : 
    1138      299764 :     result.k_val = k_val_local;
    1139      299764 :     result.dim = dim_in;
    1140             : 
    1141             :     /* NB, k_val_local  may be changed in some sub encoding routines */
    1142      299764 :     if ( dim_in > N_OPT ) /* use the generic dimension  function */
    1143             :     {
    1144      288596 :         vec2mind( dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem );
    1145             :     }
    1146             :     else /* if (dim_in<=N_OPT) */
    1147             :     {
    1148       11168 :         ( vec2mind_f[dim_in] )( vec_in, &k_val_local, &lead_sign_ind, &result.index );
    1149       11168 :         result.size = direct_msize( dim_in, k_val_local ); /* k_val_local not used for  dim==1 */
    1150             :     }
    1151      299764 :     result.lead_sign_ind = (int16_t) lead_sign_ind;
    1152             : 
    1153      299764 :     return result;
    1154             : }
    1155             : 
    1156             : /*-------------------------------------------------------------------*
    1157             :  * get_size_mpvq_calc_offset()
    1158             :  *
    1159             :  *  uint32_t h_mem[1 + KMAX +1 ];
    1160             :  *   example using fixed size of offset vector input help variable
    1161             :  *-------------------------------------------------------------------*/
    1162             : 
    1163             : /*! r: size, dim, k_val */
    1164      885486 : PvqEntry get_size_mpvq_calc_offset(
    1165             :     const int16_t dim_in,   /* i  : dimension                */
    1166             :     const int16_t k_val_in, /* i  : nb unit pulses           */
    1167             :     uint32_t *h_mem         /* o  : offsets                  */
    1168             : )
    1169             : {
    1170             :     PvqEntry entry;
    1171             : 
    1172      885486 :     entry.dim = dim_in;
    1173      885486 :     entry.k_val = k_val_in;
    1174      885486 :     entry.index = 0U;        /* avoid gcc warning in struct passing */
    1175      885486 :     entry.lead_sign_ind = 0; /* avoid gcc warning in struct passing */
    1176      885486 :     if ( dim_in > N_OPT )    /* non-direct solutions,  use A+U relation */
    1177             :     {
    1178      852288 :         entry.size = nm_h_prep_opt( entry.dim, entry.k_val, h_mem );
    1179             :     }
    1180             :     else
    1181             :     {
    1182       33198 :         entry.size = direct_msize( dim_in, entry.k_val ); /* ues equations,  h_mem is not used */
    1183             :     }
    1184             : 
    1185             : 
    1186      885486 :     return entry;
    1187             : }
    1188             : 
    1189             : /*-------------------------------------------------------------------*
    1190             :  * mpvq_decode_vec()
    1191             :  *-------------------------------------------------------------------*/
    1192             : 
    1193             : /*! r: void */
    1194      885486 : void mpvq_decode_vec(
    1195             :     const PvqEntry *entry, /* i  : sign_ind, index, dim, k_val */
    1196             :     uint32_t *h_mem,       /* i  : A/U offsets                 */
    1197             :     int16_t *vec_out       /* o  : pulse train                 */
    1198             : )
    1199             : {
    1200             :     int16_t i, leading_sign;
    1201      885486 :     const IND2VECFUNCM mind2vec_f[N_OPT + 1] = { NULL, mind2vec_one, mind2vec_two, mind2vec_three, mind2vec_four, mind2vec_five }; /*IND2VECFUNCM vector can be static global  */
    1202             : 
    1203    12213090 :     for ( i = 0; i < entry->dim; i++ )
    1204             :     {
    1205    11327604 :         vec_out[i] = ZERO; /* set all of short output vector to zero */
    1206             :     }
    1207             : 
    1208      885486 :     leading_sign = 1;
    1209      885486 :     if ( entry->lead_sign_ind )
    1210             :     {
    1211      442128 :         leading_sign = -1;
    1212             :     }
    1213             : 
    1214      885486 :     if ( entry->k_val != 0 )
    1215             :     {
    1216      885486 :         if ( entry->dim > N_OPT ) /* N_OPT  */
    1217             :         {
    1218             :             /*  generic */
    1219      852288 :             mind2vec( entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem );
    1220             :         }
    1221             :         else
    1222             :         {
    1223             :             /*  specialized functions */
    1224       33198 :             ( mind2vec_f[entry->dim] )( entry->k_val, leading_sign, entry->index, vec_out );
    1225             :         }
    1226             :     }
    1227             : 
    1228      885486 :     return;
    1229             : }
    1230             : 
    1231             : #ifdef ONE_U
    1232             : #undef ZERO
    1233             : #undef ONE
    1234             : #undef ONE_U
    1235             : #undef TWO
    1236             : #undef MAXBIT
    1237             : #undef MINNEG
    1238             : #undef SIGNBIT
    1239             : #undef UDIVBY3
    1240             : #endif
    1241             : 
    1242             : #endif

Generated by: LCOV version 1.14