Shop OBEX P1 Docs P2 Docs Learn Events
Is there a SPIN version of Float Log? — Parallax Forums

Is there a SPIN version of Float Log?

Bobb FwedBobb Fwed Posts: 1,119
edited 2013-02-08 12:53 in Propeller 1
I've been using Float32 for the FLog function, but it means I start the PASM cog for essentially a single instruction. Seems very inefficient. FloatMath does everything else I need in SPIN except Logs I'm sure someone has written the Float Log in SPIN.
Who has it!?
FLT.start
    temp := FLT.FRound(FLT.FAdd(FLT.FMul(-379.223, FLT.Log(FLT.FFloat(rtime))), 4054.36))
    FLT.stop
Seems a bit wasteful.

Comments

  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-02-07 10:02
    No one?
    Maybe someone can help unroll the PASM code?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-02-07 12:40
    I would just use the F32 floating point library. It's fast enough (+100us to start up). It doesn't take that much memory (2K+). It takes only one cog.
  • lonesocklonesock Posts: 917
    edited 2013-02-07 13:13
    Out of curiosity, what is your input range, and would you accept an approximation?

    thanks,
    Jonathan
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-02-07 13:41
    The range is from 1000 to 15000 (just a quick guess -- with a little breathing room). I'm measuring a temperature with a thermistor using an RC circuit (I have the exact math somewhere, but a 70F room makes the rtime variable set to somewhere around 6000), and I only need to measure between 50F and 175F, so that range can probably be a lot smaller.

    An approximation would be just fine (even a quite loose approximation), I only need readouts in 5-degree increments (i.e. "temp is between 65 and 70", or "...105 and 110").

    I am running this project on a battery so I am trying to use as little power as possible, hence my oposition to launching another cog. I also don't mind if it's slow. I'm already running at 40MHz and trying to squeeze some things down so I can run it at 20MHz.
  • lonesocklonesock Posts: 917
    edited 2013-02-07 14:12
    OK, here's a couple of decent approximations (note that the input 'val' does need to be in floating format, and the output is also a float):
    PUB exp( val ) : exp_val
      exp_val := f32.FMul( val, 12102203.0 )
      exp_val := f32.FRound( exp_val )
      exp_val += constant( (127 << 23) - 361007 )
    
    PUB ln( val ) : ln_val
      val -= constant( (127 << 23) - 361007 )
      ln_val := f32.FFloat( val )
      ln_val := f32.FDiv( ln_val, 12102203.0 )
    
    It just uses the fact that a float is basically stored as a log/linear representation in base 2 (with the log2 portion having an offset of 127). This was converted from some C code I found a long time ago, can't remember where...I modified the constants a tiny bit.

    Note: since you already have a multiplier, that could simplify when worked into this equation (since the multiplication is basically a factor of 2^23, and a conversion from base 2 to base e).

    Jonathan
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-02-07 14:33
    Yay!
    It gives me an error of about a degree, but that is well within specification.

    Thanks!
  • lonesocklonesock Posts: 917
    edited 2013-02-07 14:41
    You're welcome, I'm just glad it's accurate enough!

    Jonathan
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-07 15:39
    Bob, do you really have to do this with floats? It is pretty easy to calculate log or bitlog using integer math, fast, no extra cogs.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-02-07 16:05
    I don't think there is enough precision without it. The formula:

    ln(x) * -379.223 + 4054.36

    Example: x = 6000, result is 755, which equates to 75.5F

    The log would produce such a small/imprecise number, I think I loose too much right in the first operation. The multiply and add wouldn't be an issue.
    The same input would produce 1022 (102.2F) -- that's a bit of an error.
    I'm no mathematician, is there some way to apply the multiply to x before the log?

    Edit: a more correct range: 350 to 13000
  • lonesocklonesock Posts: 917
    edited 2013-02-07 16:52
    You can move the multiplication inside the Ln(), but the operation changes to power. So: y*ln(x) => ln(x^y). For integer only, I think the closest approximation I can come is this:

    f = (4324267 + 268 * v) / (2133 + v)

    I think it's within about 5 degrees over the 350 to 13000 range.

    Jonathan
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-07 22:06
    No need for loss of precision. It comes down to scale factors. The base 2 log uses the hub table, and from then on the program can maintain 12 bit precision as it converts from base 2, to base e, and then does the * and the +. All integer math. Demo attached.
    [SIZE=1][FONT=courier new]  pst.str(string(13,13,"enter number from 350 to 13000: "))
      x := pst.decIn
      x := Log2(x) * 2 ** 1488522235 ' lg2 to ln, 12 bit mantissa
      x := x ** 1048576000           ' binary to decimal fixed point
      Show(x,3)   ' show the ln(x) value
      x := (x * -37922 + 405486000) / 100000 ' calc & discard extra digits.
      Show(x,1)   ' show the temperature
    [/FONT][/SIZE]
    
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-02-08 09:13
    Thanks a lot Tracy. I simplified it down to this:
    PUB rcToTemp (rcval) : temp
    '' thanks to Tracy Allen
                     
      rcval := Log2(rcval) << 1 ** 1488522235                ' log2 to ln, 12 bit mantissa
      rcval **= 1048576000                                   ' binary to decimal fixed point
      RETURN (rcval * -37922 + 405486000) / 100000           ' calc & discard extra digits.
    
    PUB Log2 (value) | characteristic, mantissa
    '' thanks to Tracy Allen
    
      characteristic := >| value - 1
      mantissa := value >< characteristic >< 12             ' left justify to 12 bits, bitlog:
      mantissa := WORD[$C000 + mantissa]                    ' fractional part of log2(x), 16 bits mantissa
      mantissa := (mantissa + 8) >> 4                       ' round off to make it a 12 bit mantissa for our purposes (reduces precision!)
      RETURN characteristic << 12 + mantissa
    
  • lonesocklonesock Posts: 917
    edited 2013-02-08 10:13
    Tracy, nice!

    I always forget about the ROM tables. [8^/

    Jonathan
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-02-08 12:53
    'Just in case this is what the OP was really after, another spin version of float log:

    2565370_o.gif

    :)

    -Phil
Sign In or Register to comment.