| ??? 10/05/07 01:44 Modified: 10/05/07 01:59 Read: times |
#145437 - Implementation and precision Responding to: ???'s previous message |
This post shows the C implementation of the algorithm in this post.
http://www.8052.com/forum/read.phtml?id=145409 To compare the result of this algorithm with double precision log function on PC, C implementation was applied. Scan through the entire integer range, 0001H - 0FFFFH, the difference was fit in this precision. (-2.42371/256, +0/256) As you can see, the code is easily ported to ASM. Tsuneo
//
// Calculation of log10( x )
// input: unsigned 16 bit integer
// output: 16 bit fixed point
// MSB: integer
// LSB: decimal
//
// precision:
// comparead with double precision floating function
// -2.42371/256, +0/256
//
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
enum {MSB, LSB}; // big endian: for KEIL
//enum {LSB, MSB}; // little endian: for SDCC
typedef union { // union to split 2 byte value
uint i;
uchar c[2];
} T2byte;
#define BITS 16 // number of bits
#define LOG2 77 // log10( 2 ) * 256 = 77.0637
//
// Table of log2( x + 1 ) (0 <= x < 1)
// Actual calculation is
// y = floor( log2( 1 + n / 256 ) * 256 + 0.5 )
//
static uchar code log2_tbl[] = {
0, 1, 3, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21,
22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42,
44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 57, 59, 60, 61, 62,
63, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81,
82, 84, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99,
100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 178,
179, 180, 181, 182, 183, 184, 185, 185, 186, 187, 188, 189, 190, 191, 192, 192,
193, 194, 195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206,
207, 208, 208, 209, 210, 211, 212, 212, 213, 214, 215, 216, 216, 217, 218, 219,
220, 220, 221, 222, 223, 224, 224, 225, 226, 227, 228, 228, 229, 230, 231, 231,
232, 233, 234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, 244,
244, 245, 246, 247, 247, 248, 249, 249, 250, 251, 252, 252, 253, 254, 255, 255
};
uint log10( uint x )
{
T2byte val;
T2byte result;
// calculation of log2( x )
val.i = x;
result.c[MSB] = BITS;
// shif left until carry sees '1'
while ( (val.c[MSB] & 0x80) == 0 ) {
val.i <<= 1;
--result.c[MSB];
}
val.i <<= 1;
--result.c[MSB]; // integer part is calculated
// get decimal with table
result.c[LSB] = log2_tbl[ val.c[MSB] ];
// convert to log10, with rounding
return (uint)(( (ulong)result.i * LOG2 + 0x80 ) >> 8);
}
|



