LCOV - code coverage report
Current view: top level - lib_com - math_op.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 89 95 93.7 %
Date: 2025-08-23 01:22:27 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*___________________________________________________________________________
       2             :  |                                                                           |
       3             :  |  This file contains mathematic operations in fixed point.                 |
       4             :  |                                                                           |
       5             :  |  Isqrt()              : inverse square root (16 bits precision).          |
       6             :  |  Pow2()               : 2^x  (16 bits precision).                         |
       7             :  |  Log2()               : log2 (16 bits precision).                         |
       8             :  |  Dot_product()        : scalar product of <x[],y[]>                       |
       9             :  |                                                                           |
      10             :  |  In this file, the values use theses representations:                     |
      11             :  |                                                                           |
      12             :  |  Word32 L_32     : standard signed 32 bits format                         |
      13             :  |  Word16 hi, lo   : L_32 = hi<<16 + lo<<1  (DPF - Double Precision Format) |
      14             :  |  Word32 frac, Word16 exp : L_32 = frac << exp-31  (normalised format)     |
      15             :  |  Word16 int, frac        : L_32 = int.frac        (fractional format)     |
      16             :  |___________________________________________________________________________|
      17             : */
      18             : 
      19             : #include "stl.h"
      20             : #include "math_op.h"
      21             : #include "rom_basic_math.h"
      22             : 
      23             : #include <stdlib.h>
      24             : #include <stdio.h>
      25             : 
      26             : /*___________________________________________________________________________
      27             :  |                                                                           |
      28             :  |   Function Name : Isqrt                                                   |
      29             :  |                                                                           |
      30             :  |       Compute 1/sqrt(L_x).                                                |
      31             :  |       if L_x is negative or zero, result is 1 (7fffffff).                 |
      32             :  |---------------------------------------------------------------------------|
      33             :  |  Algorithm:                                                               |
      34             :  |                                                                           |
      35             :  |   1- Normalization of L_x.                                                |
      36             :  |   2- call Isqrt_lc(L_x, exponant)                                         |
      37             :  |   3- L_y = L_x << exponant                                                |
      38             :  |___________________________________________________________________________|
      39             : */
      40     5966083 : Word32 Isqrt(            /* (o) Q31 : output value (range: 0<=val<1)         */
      41             :               Word32 L_x /* (i) Q0  : input value  (range: 0<=val<=7fffffff) */
      42             : )
      43             : {
      44             :     Word16 exp;
      45             :     Word32 L_y;
      46             : 
      47     5966083 :     exp = norm_l( L_x );
      48     5966083 :     L_x = L_shl( L_x, exp ); /* L_x is normalized */
      49     5966083 :     exp = sub( 31, exp );
      50             : 
      51     5966083 :     L_x = Isqrt_lc( L_x, &exp );
      52             : 
      53     5966083 :     L_y = L_shl( L_x, exp ); /* denormalization   */
      54             : 
      55     5966083 :     return ( L_y );
      56             : }
      57             : 
      58             : /*___________________________________________________________________________
      59             :  |                                                                           |
      60             :  |   Function Name : Isqrt_lc                                                |
      61             :  |                                                                           |
      62             :  |       Compute 1/sqrt(value).                                              |
      63             :  |       if value is negative or zero, result is 1 (frac=7fffffff, exp=0).   |
      64             :  |---------------------------------------------------------------------------|
      65             :  |  Algorithm:                                                               |
      66             :  |                                                                           |
      67             :  |   The function 1/sqrt(value) is approximated by a table and linear        |
      68             :  |   interpolation.                                                          |
      69             :  |                                                                           |
      70             :  |   1- If exponant is odd then shift fraction right once.                   |
      71             :  |   2- exponant = -((exponant-1)>>1)                                        |
      72             :  |   3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |
      73             :  |   4- a = bit10-b24                                                        |
      74             :  |   5- i -=16                                                               |
      75             :  |   6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2            |
      76             :  |___________________________________________________________________________|
      77             : */
      78    11829646 : Word32 Isqrt_lc(
      79             :     Word32 frac, /* (i)   Q31: normalized value (1.0 < frac <= 0.5) */
      80             :     Word16 *exp  /* (i/o)    : exponent (value = frac x 2^exponent) */
      81             : )
      82             : {
      83             :     Word16 i, a;
      84             :     Word32 L_tmp;
      85             : 
      86    11829646 :     IF( frac <= (Word32) 0 )
      87             :     {
      88        5801 :         *exp = 0;
      89        5801 :         move16();
      90        5801 :         return 0x7fffffff; /*0x7fffffff*/
      91             :     }
      92             : 
      93             :     /* If exponant odd -> shift right by 10 (otherwise 9) */
      94    11823845 :     L_tmp = L_shr( frac, shift_Isqrt_lc[s_and( *exp, 1 )] );
      95             : 
      96             :     /* 1) -16384 to shift left and change sign                 */
      97             :     /* 2) 32768 to Add 1 to Exponent like it was divided by 2  */
      98             :     /* 3) We let the mac_r add another 0.5 because it imitates */
      99             :     /*    the behavior of shr on negative number that should   */
     100             :     /*    not be rounded towards negative infinity.            */
     101             :     /* It replaces:                                            */
     102             :     /*    *exp = negate(shr(sub(*exp, 1), 1));   move16();     */
     103    11823845 :     *exp = mac_r( 32768, *exp, -16384 );
     104    11823845 :     move16();
     105             : 
     106    11823845 :     a = extract_l( L_tmp ); /* Extract b10-b24 */
     107    11823845 :     a = lshr( a, 1 );
     108             : 
     109    11823845 :     i = mac_r( L_tmp, -16 * 2 - 1, 16384 ); /* Extract b25-b31 minus 16 */
     110             : 
     111    11823845 :     L_tmp = L_msu( L_table_isqrt[i], table_isqrt_diff[i], a ); /* table[i] << 16 - diff*a*2 */
     112             : 
     113    11823845 :     return L_tmp;
     114             : }
     115             : 
     116             : /*___________________________________________________________________________
     117             :  |                                                                           |
     118             :  |   Function Name : Pow2()                                                  |
     119             :  |                                                                           |
     120             :  |     L_x = pow(2.0, exponant.fraction)         (exponant = interger part)  |
     121             :  |         = pow(2.0, 0.fraction) << exponant                                |
     122             :  |---------------------------------------------------------------------------|
     123             :  |  Algorithm:                                                               |
     124             :  |                                                                           |
     125             :  |   The function Pow2(L_x) is approximated by a table and linear            |
     126             :  |   interpolation.                                                          |
     127             :  |                                                                           |
     128             :  |   1- i = bit10-b15 of fraction,   0 <= i <= 31                            |
     129             :  |   2- a = bit0-b9   of fraction                                            |
     130             :  |   3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2                 |
     131             :  |   4- L_x = L_x >> (30-exponant)     (with rounding)                       |
     132             :  |___________________________________________________________________________|
     133             : */
     134             : 
     135     7668069 : Word32 Pow2(                  /* (o) Q0  : result       (range: 0<=val<=0x7fffffff) */
     136             :              Word16 exponant, /* (i) Q0  : Integer part.      (range: 0<=val<=30)   */
     137             :              Word16 fraction  /* (i) Q15 : Fractionnal part.  (range: 0.0<=val<1.0) */
     138             : )
     139             : {
     140             :     Word16 exp, i, a;
     141             :     Word32 L_x;
     142             : 
     143             : 
     144     7668069 :     i = mac_r( -32768, fraction, 32 ); /* Extract b10-b16 of fraction */
     145     7668069 :     a = s_and( fraction, 0x3ff );      /* Extract  b0-b9  of fraction */
     146             : 
     147     7668069 :     L_x = L_deposit_h( table_pow2[i] );            /* table[i] << 16   */
     148     7668069 :     L_x = L_mac( L_x, table_pow2_diff_x32[i], a ); /* L_x -= diff*a*2  */
     149             : 
     150     7668069 :     exp = sub( 30, exponant );
     151             : 
     152     7668069 :     L_x = L_shr_r( L_x, exp );
     153             : 
     154             : 
     155     7668069 :     return L_x;
     156             : }
     157             : 
     158             : /*___________________________________________________________________________
     159             :  |                                                                           |
     160             :  |   Function Name : Dot_product12()                                         |
     161             :  |                                                                           |
     162             :  |       Compute scalar product of <x[],y[]> using accumulator.              |
     163             :  |                                                                           |
     164             :  |       The result is normalized (in Q31) with exponent (0..30).            |
     165             :  |---------------------------------------------------------------------------|
     166             :  |  Algorithm:                                                               |
     167             :  |                                                                           |
     168             :  |       dot_product = sum(x[i]*y[i])     i=0..N-1                           |
     169             :  |___________________________________________________________________________|
     170             : */
     171             : 
     172     2194215 : Word32 Dot_product12_o(                    /* (o) Q31: normalized result (1 < val <= -1) */
     173             :                         const Word16 x[],  /* (i) 12bits: x vector                       */
     174             :                         const Word16 y[],  /* (i) 12bits: y vector                       */
     175             :                         const Word16 lg,   /* (i)    : vector length                     */
     176             :                         Word16 *exp,       /* (o)    : exponent of result (0..+30)       */
     177             :                         Flag *Overflow_out /* o :  propagating the Overflow flag to upper level, set to NULL to ignore internal overflows */
     178             : )
     179             : {
     180             :     Word16 i, sft;
     181             :     Word32 L_sum;
     182     2194215 :     Flag Overflow_ignored = 0;
     183             : 
     184     2194215 :     L_sum = L_mac_o( 1, x[0], y[0], &Overflow_ignored );
     185   173705799 :     FOR( i = 1; i < lg; i++ )
     186             :     {
     187   171511584 :         L_sum = L_mac_o( L_sum, x[i], y[i], Overflow_out ? Overflow_out : &Overflow_ignored );
     188             :     }
     189             : 
     190             :     /* Normalize acc in Q31 */
     191             : 
     192     2194215 :     sft = norm_l( L_sum );
     193     2194215 :     L_sum = L_shl( L_sum, sft );
     194             : 
     195     2194215 :     *exp = sub( 30, sft );
     196     2194215 :     move16(); /* exponent = 0..30 */
     197             : 
     198     2194215 :     return L_sum;
     199             : }
     200             : 
     201     2194215 : Word32 Dot_product12(                   /* (o) Q31: normalized result (1 < val <= -1) */
     202             :                       const Word16 x[], /* (i) 12bits: x vector                       */
     203             :                       const Word16 y[], /* (i) 12bits: y vector                       */
     204             :                       const Word16 lg,  /* (i)    : vector length                     */
     205             :                       Word16 *exp       /* (o)    : exponent of result (0..+30)       */
     206             : )
     207             : {
     208             :     /* Ignore internal overflows */
     209     2194215 :     return Dot_product12_o( x, y, lg, exp, NULL );
     210             : }
     211             : 
     212             : /*___________________________________________________________________________
     213             :  |                                                                           |
     214             :  |   Function Name : Energy_scale()                                          |
     215             :  |                                                                           |
     216             :  |       Compute energy of signal (scaling the input if specified)           |
     217             :  |                                                                           |
     218             :  |       The result is normalized (in Q31) with exponent (0..30).            |
     219             :  |___________________________________________________________________________|
     220             : */
     221             : 
     222         315 : Word32 Energy_scale(                   /* (o) : Q31: normalized result (1 < val <= -1)  */
     223             :                      const Word16 x[], /* (i) : input vector x                          */
     224             :                      const Word16 lg,  /* (i) : vector length                           */
     225             :                      Word16 expi,      /* (i) : exponent of input                       */
     226             :                      Word16 *exp       /* (o) : exponent of result (0..+30)             */
     227             : )
     228             : {
     229             :     Word16 i, sft, tmp;
     230             :     Word32 L_sum;
     231             : #ifndef ISSUE_1836_replace_overflow_libcom
     232             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     233             :     Flag Overflow = 0;
     234             : #endif
     235             : #endif
     236             : 
     237             : 
     238         315 :     L_sum = 0; /* just to avoid superflous compiler warning about uninitialized use of L_sum */
     239             : 
     240         315 :     IF( expi == 0 )
     241             :     {
     242             : #ifdef ISSUE_1836_replace_overflow_libcom
     243         102 :         L_sum = L_mac_sat( 1, x[0], x[0] );
     244       20000 :         FOR( i = 1; i < lg; i++ )
     245             :         {
     246       19898 :             L_sum = L_mac_sat( L_sum, x[i], x[i] );
     247             :         }
     248             : #else
     249             :         L_sum = L_mac_o( 1, x[0], x[0], &Overflow );
     250             :         FOR( i = 1; i < lg; i++ )
     251             :         {
     252             :             L_sum = L_mac_o( L_sum, x[i], x[i], &Overflow );
     253             :         }
     254             : #endif
     255             :     }
     256         315 :     IF( expi < 0 )
     257             :     {
     258           0 :         sft = lshl( -32768 /* 0x8000 */, expi );
     259           0 :         tmp = mult_r( x[0], sft );
     260           0 :         L_sum = L_mac( 1, tmp, tmp );
     261           0 :         FOR( i = 1; i < lg; i++ )
     262             :         {
     263           0 :             tmp = mult_r( x[i], sft );
     264             : #ifdef ISSUE_1836_replace_overflow_libcom
     265           0 :             L_sum = L_mac_sat( L_sum, tmp, tmp );
     266             : #else
     267             :             L_sum = L_mac_o( L_sum, tmp, tmp, &Overflow );
     268             : #endif
     269             :         }
     270             :     }
     271         315 :     IF( expi > 0 )
     272             :     {
     273             : #ifdef ISSUE_1836_replace_overflow_libcom
     274         213 :         tmp = shl_sat( x[0], expi );
     275         213 :         L_sum = L_mac_sat( 1, tmp, tmp );
     276       34016 :         FOR( i = 1; i < lg; i++ )
     277             :         {
     278       33803 :             tmp = shl_sat( x[i], expi );
     279       33803 :             L_sum = L_mac_sat( L_sum, tmp, tmp );
     280             :         }
     281             : #else
     282             :         tmp = shl_o( x[0], expi, &Overflow );
     283             :         L_sum = L_mac_o( 1, tmp, tmp, &Overflow );
     284             :         FOR( i = 1; i < lg; i++ )
     285             :         {
     286             :             tmp = shl_o( x[i], expi, &Overflow );
     287             :             L_sum = L_mac_o( L_sum, tmp, tmp, &Overflow );
     288             :         }
     289             : #endif
     290             :     }
     291             : 
     292             :     /* Normalize acc in Q31 */
     293             : 
     294         315 :     sft = norm_l( L_sum );
     295         315 :     L_sum = L_shl( L_sum, sft );
     296             : 
     297         315 :     *exp = sub( 30, sft );
     298         315 :     move16(); /* exponent = 0..30 */
     299             : 
     300             : 
     301         315 :     return L_sum;
     302             : }
     303             : 
     304       81009 : Word32 Sqrt_l(             /* o : output value,                          Q31 */
     305             :                Word32 L_x, /* i : input value,                           Q31 */
     306             :                Word16 *exp /* o : right shift to be applied to result,   Q1  */
     307             : )
     308             : {
     309             :     /*
     310             :         y = sqrt(x)
     311             : 
     312             :         x = f * 2^-e,   0.5 <= f < 1   (normalization)
     313             : 
     314             :         y = sqrt(f) * 2^(-e/2)
     315             : 
     316             :         a) e = 2k   --> y = sqrt(f)   * 2^-k  (k = e div 2,
     317             :                                                0.707 <= sqrt(f) < 1)
     318             :         b) e = 2k+1 --> y = sqrt(f/2) * 2^-k  (k = e div 2,
     319             :                                                0.5 <= sqrt(f/2) < 0.707)
     320             :      */
     321             : 
     322             :     Word16 e, i, a, tmp;
     323             :     Word32 L_y;
     324             : 
     325       81009 :     if ( L_x <= 0 )
     326             :     {
     327         123 :         *exp = 0;
     328         123 :         move16();
     329         123 :         return L_deposit_l( 0 );
     330             :     }
     331             : 
     332       80886 :     e = s_and( norm_l( L_x ), 0x7FFE ); /* get next lower EVEN norm. exp  */
     333       80886 :     L_x = L_shl( L_x, e );              /* L_x is normalized to [0.25..1) */
     334       80886 :     *exp = e;
     335       80886 :     move16(); /* return 2*exponent (or Q1)      */
     336             : 
     337       80886 :     L_x = L_shr( L_x, 9 );
     338       80886 :     a = extract_l( L_x ); /* Extract b10-b24                */
     339       80886 :     a = lshr( a, 1 );
     340             : 
     341       80886 :     i = mac_r( L_x, -16 * 2 - 1, 16384 ); /* Extract b25-b31 minus 16 */
     342             : 
     343       80886 :     L_y = L_deposit_h( sqrt_table[i] );            /* table[i] << 16                 */
     344       80886 :     tmp = sub( sqrt_table[i], sqrt_table[i + 1] ); /* table[i] - table[i+1])         */
     345       80886 :     L_y = L_msu( L_y, tmp, a );                    /* L_y -= tmp*a*2                 */
     346             : 
     347             :     /* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */
     348             : 
     349       80886 :     return ( L_y );
     350             : }
     351             : 
     352             : /*---------------------------------------------------------------------------*
     353             :  * L_Frac_sqrtQ31
     354             :  *
     355             :  * Calculate square root from fractional values (Q31 -> Q31)
     356             :  * Uses 32 bit internal representation for precision
     357             :  *---------------------------------------------------------------------------*/
     358     4543762 : Word32 L_Frac_sqrtQ31(                /* o  : Square root if input */
     359             :                        const Word32 x /* i  : Input                */
     360             : )
     361             : {
     362             :     Word32 log2_work;
     363             :     Word16 log2_int, log2_frac;
     364             : 
     365     4543762 :     test();
     366     4543762 :     if ( x > 0 )
     367             :     {
     368     4465945 :         log2_int = norm_l( x );
     369     4465945 :         log2_frac = Log2_norm_lc( L_shl( x, log2_int ) );
     370             : 
     371     4465945 :         log2_work = L_msu( ( 31 + 30 ) * 65536L / 2, 16384, log2_int );
     372     4465945 :         log2_work = L_mac0( log2_work, log2_frac, 1 );
     373             : 
     374     4465945 :         log2_frac = L_Extract_lc( log2_work, &log2_int );
     375             : 
     376     4465945 :         return Pow2( log2_int, log2_frac );
     377             :     }
     378       77817 :     return 0;
     379             : }
     380             : 
     381             : /*----------------------------------------------------------------------------------*
     382             :  * Frac_sqrt
     383             :  *
     384             :  * Calculate square root from fractional values (Q15 -> Q15)
     385             :  *----------------------------------------------------------------------------------*/
     386      670240 : Word16 Frac_sqrt(                /* o  : Square root if input */
     387             :                   const Word16 x /* i  : Input                */
     388             : )
     389             : {
     390      670240 :     return round_fx( L_Frac_sqrtQ31( L_deposit_h( x ) ) );
     391             : }
     392             : 
     393             : 
     394             : /*----------------------------------------------------------------------------------*
     395             :  * i_mult2
     396             :  *
     397             :  * Faster Integer Multiplication
     398             :  *----------------------------------------------------------------------------------*/
     399             : 
     400    10606684 : Word16 i_mult2( Word16 a, Word16 b )
     401             : {
     402    10606684 :     return extract_l( L_mult0( a, b ) );
     403             : }

Generated by: LCOV version 1.14