rtphone/src/libs/libevs/basic_math/log2.cpp

212 lines
5.0 KiB
C++
Executable File

/********************************************************************************
*
* File : log2.c
* Purpose : Computes log2(L_x)
*
********************************************************************************
*/
/*
********************************************************************************
* INCLUDE FILES
********************************************************************************
*/
#include "stl.h"
#include "math_op.h"
#include <assert.h>
#include "rom_basic_math.h"
#include "options.h"
#define LW_SIGN (Word32)0x80000000 /* sign bit */
#define LW_MIN (Word32)0x80000000
#define LW_MAX (Word32)0x7fffffff
#define SW_SIGN (Word16)0x8000 /* sign bit for Word16 type */
#define SW_MIN (Word16)0x8000 /* smallest Ram */
#define SW_MAX (Word16)0x7fff /* largest Ram */
/*
********************************************************************************
* PUBLIC PROGRAM CODE
********************************************************************************
*/
/*************************************************************************
*
* FUNCTION: Log2_norm_lc()
*
* 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
*
*************************************************************************/
Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x /* (i) : input value (normalized) */
)
{
Word16 i, a;
Word16 y;
if (L_x <= 0)
L_x = L_deposit_h(0x4000);
L_x = L_shr (L_x, 9);
a = extract_l (L_x); /* Extract b10-b24 of fraction */
a = lshr(a, 1);
i = mac_r(L_x, -32*2-1, 16384); /* Extract b25-b31 minus 32 */
y = mac_r(L_table_Log2_norm_lc[i], table_diff_Log2_norm_lc[i], a); /* table[i] << 16 - diff*a*2 */
return y;
}
Word32 log10_fx(Word32 Linput)
{
Word16 n1, frac, p1, p2, q1;
Word32 Ltemp1, Ltemp2;
Word32 L_tmp;
if (Linput<=0) return(LW_MIN);
n1=norm_l(Linput);
Ltemp1=(Word32)L_shl(Linput,n1);
Ltemp2=L_mult(extract_h(Ltemp1),0x40);
frac=extract_l(Ltemp2);
p1=log2_tab[sub(extract_h(Ltemp2),0x20)];
p2=log2_tab[sub(extract_h(Ltemp2),0x1F)];
Ltemp2=L_mult(n1,0x200);
n1=extract_l(Ltemp2);
Ltemp1=L_add(L_deposit_h(p1),0x8000); /* Add rounding bit */
IF(frac >= 0)
{
Ltemp1=L_sub(Ltemp1,(Word32)L_mult0(p1,frac));
Ltemp1=L_add(Ltemp1,(Word32)L_mult0(p2,frac));
}
ELSE
{
L_tmp = L_add(65536,frac);
L_tmp = L_tmp*p1;
Ltemp1=L_sub(Ltemp1,L_tmp);
L_tmp = L_add(65536,frac);
L_tmp = L_tmp*p2;
Ltemp1=L_add(Ltemp1,L_tmp);
}
q1=extract_h(Ltemp1);
Ltemp1=L_mult(q1,0x6054);
Ltemp1=L_msu(Ltemp1,0x6054,n1);
return(L_shr(Ltemp1,1));
}
Word32 pow_10(Word32 x , Word16 *Q)
{
Word16 xl,xh, t1, t2, n;
Word32 Ltemp1;
Word32 Lacc;
Word32 L_tmp;
Word16 n1,i;
Word16 count = 0;
move16();;
xl=extract_l(x);
xh=extract_h(x);
IF(xl < 0)
{
L_tmp = L_add(65536,xl);
Ltemp1=(Word32) (0x6a4d*L_tmp );
}
ELSE
{
Ltemp1=L_mult0(0x6a4d,xl);
}
Ltemp1=L_add(L_shr(Ltemp1,16),L_shr(L_mult(xh,0x6a4d),1));
Lacc=L_sub(-1L, Ltemp1); /* Lacc=~Lacc, 1's complement */
t1=extract_l(L_shr(Lacc,7));
Ltemp1=L_shr(Ltemp1,7);
n1 = extract_h(Ltemp1);
n=sub(n1,14);
*Q = 14; move16();
IF(t1<0)
{
L_tmp = L_add(65536,t1);
t2=extract_h(L_tmp*L_tmp);
}
ELSE
{
t2=extract_h(L_mult0(t1,t1));
}
Lacc = L_deposit_h(0x1FEF);
IF(t2 < 0)
{
L_tmp = L_add(65536,t2);
Lacc = L_add(Lacc,(Word32)(L_tmp*0x057C));
}
ELSE
{
Lacc = L_add(Lacc,(Word32)L_mult0(t2,0x057C));
}
IF(t1 < 0)
{
L_tmp = L_add(65536,t1);
Lacc = L_sub(Lacc,(Word32)(L_tmp*0x155C));
}
ELSE
{
Lacc = L_sub(Lacc,(Word32)L_mult0(t1,0x155C));
}
L_tmp = Lacc;
FOR(i =1 ;i <= n ;i++)
{
Overflow = 0; move16();
L_tmp = L_shl(L_tmp,i);
IF(Overflow)
{
count = add(count,1);
}
}
*Q = sub(*Q,count); move16();
return(L_shl(Lacc,sub(n,count)));
}
Word16 Log2_lc( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x, /* (i) : input value */
Word16 *exponent /* (o) : Integer part of Log2. (range: 0<=val<=30) */
)
{
Word16 exp;
if (L_x <= 0)
L_x = L_deposit_l(0x1);
exp = norm_l (L_x);
*exponent = sub(30, exp); move16();
return Log2_norm_lc(L_shl(L_x, exp));
}