#include #include #include #include #include static unsigned short log2_table[17]; void generate_log2_table (void) { int i; for(i=0;i<16;i++) log2_table[i]=(unsigned short)(4096.0*log(1.0+((0.0+i)/16.0))/log(2)); } void dump_log2_table (void) { int i; for(i=0;i<16;i++) printf("0x%04x\n",log2_table[i]); } /* fflog2 works. IN : 16-bit integer OUT: 16-bit integer as a fixedpoint 4.12-bit integer now */ unsigned short fflog2 (unsigned short x) { unsigned i = 15; /* integer part */ unsigned j; /* fractional part */ if (!x) return 0; if (x < (1<<8)) { x <<= 8; i -= 8; } if (x < (1<<12)) { x <<= 4; i -= 4; } if (x < (1<<14)) { x <<= 2; i -= 2; } if (x < (1<<15)) { x <<= 1; i -= 1; } x <<= 1; j = x >> 12; return (i<<12) | log2_table[j]; // weirdly not accurate at all //return (i<<12) | (log2_table[j] + ((unsigned)((unsigned)(x & 0xfff) * (log2_table[j+1] - log2_table[j]))) >> 12); } #ifdef LOG2 /* fflog10 works */ unsigned short fflog10 (unsigned short x) { return ((unsigned)fflog2(x) * (unsigned)(4096.0*(0.30102999566398119521373889472449/*log10(2)*/))) >> 12; } #else static unsigned short log10_table[17]; void generate_log10_table (void) { int i; for(i=0;i<16;i++) log10_table[i]=(unsigned short)(4096.0*log(1.0+((0.0+i)/16.0))/log(10)); } #define FFLOG10_2 4096.0*(0.30102999566398119521373889472449/*log10(2)*/) unsigned short fflog10 (unsigned short x) { unsigned i = (unsigned)(4096.0*4.5154499349597179282060834208674/*log10(2^15)*/); unsigned j; if (!x) return 0; if (x < (1<<8)) { x <<= 8; i -= (unsigned)(8.0*FFLOG10_2); /* 8 * log10(2) */ } if (x < (1<<12)) { x <<= 4; i -= (unsigned)(4.0*FFLOG10_2); /* 4 * log10(2) */ } if (x < (1<<14)) { x <<= 2; i -= (unsigned)(2.0*FFLOG10_2); /* 2 * log10(2) */ } if (x < (1<<15)) { x <<= 1; i -= (unsigned)(1.0*FFLOG10_2); /* 1 * log10(2) */ } x <<= 1; j = x >> 12; return i + log10_table[j]; } #endif int main (int argc, char *argv[]) { #ifdef LOG2 generate_log2_table(); #else generate_log10_table(); #endif short test1 = (unsigned short)(1*(1<<15)-1); short test2 = (unsigned short)(1*(1<<14)+1*(1<<13)+1*(1<<12)+1*(1<<11)+1*(1<<10)+1*(1<<9)+1*(1<<8)+1*(1<<7)+1*(1<<6)+1*(1<<5)+1*(1<<4)+1*(1<<3)+1*(1<<2)+0*(1<<1)); short test3 = (unsigned short)(1*(1<<14)+1*(1<<10)); short test4 = (unsigned short)(1*(1<<10)+1*(1<<8)-1); short test5 = (unsigned short)(1*(1<<8)+1*(1<<3)); short test6 = (unsigned short)(1*(1<<6)+1*(1<<3)); short test7 = (unsigned short)(1*(1<<4)+1*(1<<1)); short test8 = (unsigned short)(1*(1<<4)-1); cout << "fflog10(" << test1 << ") = " << double(fflog10(test1)) / 4096.0 << " / " << log10(test1) << endl; cout << "fflog10(" << test2 << ") = " << double(fflog10(test2)) / 4096.0 << " / " << log10(test2) << endl; cout << "fflog10(" << test3 << ") = " << double(fflog10(test3)) / 4096.0 << " / " << log10(test3) << endl; cout << "fflog10(" << test4 << ") = " << double(fflog10(test4)) / 4096.0 << " / " << log10(test4) << endl; cout << "fflog10(" << test5 << ") = " << double(fflog10(test5)) / 4096.0 << " / " << log10(test5) << endl; cout << "fflog10(" << test6 << ") = " << double(fflog10(test6)) / 4096.0 << " / " << log10(test6) << endl; cout << "fflog10(" << test7 << ") = " << double(fflog10(test7)) / 4096.0 << " / " << log10(test7) << endl; cout << "fflog10(" << test8 << ") = " << double(fflog10(test8)) / 4096.0 << " / " << log10(test8) << endl; dump_log2_table (); cout << "Press ENTER to continue..." << endl; getchar (); return 0; }