View Full Version : Odd request... Anybody have log10 in spin?

Stephen Moraco
07-21-2009, 01:54 PM
I'm working through turning on a propeller-based prototype. XBee radio, SHT11 sensor,
additional Analog Temp Sensor (so I can checkout XBee ADC and auto-reporting) and
headers for adding more sensors.

See: picasaweb.google.com/smmoraco/PropSenseAPropellerZigBeeBasedSensorPlatform (http://picasaweb.google.com/smmoraco/PropSenseAPropellerZigBeeBasedSensorPlatform)

As I grabbed code from our object exchange SHT11, XBee etc... TV out (of course!) my own
serial and full-duplex serial (ok, I'll proably drop to only one of these and not mine as I don't
need the high speed).... I find that the SHTxx code is using float32 (asm in own cog) for only
the Log10 code. I have no performance need and believe it or not I could use a freed up
cog! (ok, stop laughing... I know, eight really should be enough... http://forums.parallax.com/images/smilies/wink.gif

So, does anybody know of a spin-only version I can "leverage"?

Stephen, KZ0Q

07-21-2009, 02:17 PM
I did a ln rather than a log10 a while ago. It was a table lookup with linear interpolation. Not particular accurate but good enough for what I needed. The same system would work for this with a different tables.
It was 2 tables, a table of x values and a table of ln(x) values. You walked though the x table until you found a value >= x then got ln (i-1) and ln(i) then did a linear interpolation of the 2 values.

Nick Mueller
07-21-2009, 02:46 PM
The ln can be aproximated with:

ln x = 2 * [(x-1) / (x + 1) + (x - 1)^3 / 3(x+1)^3 + (x - 1)^5 / 5(x + 1)^5 + ... ]

for x > 0

ln N = 2.30259 log N


Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

07-21-2009, 04:20 PM
Or, you can combine Timmoore's and Nick's method:

Find the closest x0 to your x in the table of x values

Then use the Taylor expansion

log(x) approx.= ln(x0)/ln(10) + (x-x0)/(x0*ln(10)) - (x-x0)*(x-x0)/(2*x0*x0*ln(10))
иииииииииииииии[from the 2nd table]

The 1/x0*ln(10) andи 1/(2*x0*x0*ln(10) constants could be
stored in other tables, if you prefer speed.и

Many depend on how the numbers are represented in your system and what is the range for x.

If you have time enough to make something really effective, translate into SPIN the following c code, which does not use multiplication/division at all.

Here x and ln(x) are both expressed as 32-bit fixed-point values with 16 fractional bits.

int ln(int x) {
int t,y;
if(x<0x00008000) x<<=16, y-=0xb1721;
if(x<0x00800000) x<<= 8, y-=0x58b91;
if(x<0x08000000) x<<= 4, y-=0x2c5c8;
if(x<0x20000000) x<<= 2, y-=0x162e4;
if(x<0x40000000) x<<= 1, y-=0x0b172;
t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
return y;

This code is for ln, so you will need a final multiplication

log(x) = ln(x)*(1/ln(10)) = ln(x) * 0.434294