212 lines
5.0 KiB
C++
Executable File
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));
|
|
}
|