#if defined(__arm__)
#if (__ARMCC_VERSION >= 6000000)
#pragma clang section data = "SE_SOL_DSRW" text = "SE_SOL_CODE" bss = "SE_SOL_DSZI" rodata = "SE_SOL_DSCONST"
#elif (__ARMCC_VERSION >= 5000000)
#pragma arm section rwdata = "SE_DMV_DSRW", rodata = "SE_DMV_DSCONST", code = "SE_DMV_CODE", zidata = "SE_DMV_DSZI"
#else
// to do
#endif
#endif

/*
********************************************************************************
*
*      GSM AMR-NB speech codec   R98   Version 7.6.0   December 12, 2001
*                                R99   Version 3.3.0                
*                                REL-4 Version 4.1.0                
*
********************************************************************************
*
*      File             : log2.c
*      Purpose          : Computes log2(L_x)
*
********************************************************************************
*/
/*
********************************************************************************
*                         MODULE INCLUDE FILE AND VERSION ID
********************************************************************************
*/
#include "log2.h"
const char log2_id[] = "@(#)$Id $" log2_h;
 
/*
********************************************************************************
*                         INCLUDE FILES
********************************************************************************
*/
#include "typedef.h"
#include "basic_op.h"

 
/*
********************************************************************************
*                         LOCAL VARIABLES AND TABLES
********************************************************************************
*/
#include "log2.tab"     /* Table for Log2() */
 
/*
********************************************************************************
*                         PUBLIC PROGRAM CODE
********************************************************************************
*/

/*************************************************************************
 *
 *   FUNCTION:   Log2_norm()
 *
 *   PURPOSE:   Computes log2(L_x, exp),  where   L_x is positive and
 *              normalized, and exp is the normalisation exponent
 *              If L_x is negative or zero, the result is 0.
 *
 *   DESCRIPTION:
 *        The function Log2(L_x) is approximated by a table and linear
 *        interpolation. The following steps are used to compute Log2(L_x)
 *
 *           1- exponent = 30-norm_exponent
 *           2- i = bit25-b31 of L_x;  32<=i<=63  (because of normalization).
 *           3- a = bit10-b24
 *           4- i -=32
 *           5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
 *
 *************************************************************************/
void Log2_norm (
    long L_x,         /* (i) : input value (normalized)                    */
    short exp,         /* (i) : norm_l (L_x)                                */
    short *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */
    short *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1)  */
)
{
    short i, a, tmp;
    long L_y;

    if (L_x <= (long) 0)
    {
        *exponent = 0;
        *fraction = 0;
        return;
    }

    *exponent = sub (30, exp);

    L_x = L_shr (L_x, 9);
    i = extract_h (L_x);                /* Extract b25-b31 */
    L_x = L_shr (L_x, 1);
    a = extract_l (L_x);                /* Extract b10-b24 of fraction */
    a = a & (short) 0x7fff;

    i = sub (i, 32);

    L_y = L_deposit_h (table[i]);       /* table[i] << 16        */
    tmp = sub (table[i], table[i + 1]); /* table[i] - table[i+1] */
    L_y = L_msu (L_y, tmp, a);          /* L_y -= tmp*a*2        */

    *fraction = extract_h (L_y);

    return;
}
