/******************************************************************************** * * File : log2.c * Purpose : Computes log2(L_x) * ******************************************************************************** */ /* ******************************************************************************** * INCLUDE FILES ******************************************************************************** */ #include "stl.h" #include "math_op.h" #include #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)); }