Searching \ for '[PIC]: PIC Maths' in subject line. () Help us get a faster server
FAQ page: massmind.org/techref/microchip/math/index.htm?key=math
Search entire site for: 'PIC Maths'.

Exact match. Not showing close matches.
'[PIC]: PIC Maths'
2001\09\16@075035 by  I have what I thought would be a trivial problem to code in ASM (probably
for an F87*) but I can't get my head around how to do it at the moment.

I have two 8-bit values, X & Y. Each can be anywhere within a range of say
40 to 100 (allowance has to made for when one is zero).  These linear values
represent the stored energy in two capacitors according to the function
2^X(orY), where 100 is maximum, 90 a half, 80 a quarter, 70 an eighth etc.
including any integer value in between.

I need to calculate a third value Z, an 8-bit value of the same form,
equivalent to the overall stored energy of both capacitors, again in the
range of say 40 to 100. e.g. If X=90 and Y=90 then Z=100 or if X=40 and Y=40
then X=50 or if X=90 and Y=85 then Z=98 (approx.)

Using LOG(base-2) the function Z = 10*lg(2^X/10 + 2^Y/10) does what I need
in Excel (with a bit of rounding),  but I can't think of a simple way of
doing this in ASM.   I need the code to be as tight and fast as possible.

I have looked at the Log routine by Scott Dattalo and freely admit I haven't
figured out how that works but is there a much simpler way for what I am
trying to do?

Many thanks

David Binnington

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.   On Sun, 16 Sep 2001, David J Binnington wrote:

David,

You can re-write your equation like:

Z = 10*lg(x^2 + y^2)
= 10*lg(x^2 * ( 1 + (y/x)^2))
= 20*lg(x) + 10 * lg( 1 + (y/x)^2)

let v = 1+(y/x)^2

Z = 20*lg(x) + 10*lg(v)

I'd factor it this way if x is greater than y. If y is larger, then factor

Does that help?

Scott

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.  Thanks Scott.  Looks like it may make things easier.  It's getting late here
and my brain is fried at the moment.  Will look at it tomorrow in more
detail.

Thanks again.

David

> {Original Message removed}   > I have two 8-bit values, X & Y. Each can be anywhere within a range of say
> 40 to 100 (allowance has to made for when one is zero).  These linear
values
> represent the stored energy in two capacitors according to the function
> 2^X(orY), where 100 is maximum, 90 a half, 80 a quarter, 70 an eighth etc.
> including any integer value in between.
>
> I need to calculate a third value Z, an 8-bit value of the same form,
> equivalent to the overall stored energy of both capacitors, again in the
> range of say 40 to 100. e.g. If X=90 and Y=90 then Z=100 or if X=40 and
Y=40
> then X=50 or if X=90 and Y=85 then Z=98 (approx.)
>
> Using LOG(base-2) the function Z = 10*lg(2^X/10 + 2^Y/10) does what I need
> in Excel (with a bit of rounding),  but I can't think of a simple way of
> doing this in ASM.   I need the code to be as tight and fast as possible.

I don't know of any easy trick for trying to do addition in log space.  You
could use a table to convert from the log values to linear value, do the
addition, then use a table again to convert back to this log space.  That
would be relatively fast but use a lot of code space.

Why do the values need to be represented as they are?  If you can store
everything internally as linear energy values, it would simplify doing
calculations like this.  Do these values come in this way, need to go out
this way?

********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, olin embedinc.com, http://www.embedinc.com

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.   On Sun, 16 Sep 2001, Scott Dattalo wrote:

> On Sun, 16 Sep 2001, David J Binnington wrote:
>
>
> David,
>
>
> You can re-write your equation like:
>
> Z = 10*lg(x^2 + y^2)
>   = 10*lg(x^2 * ( 1 + (y/x)^2))
>   = 20*lg(x) + 10 * lg( 1 + (y/x)^2)
>
> let v = 1+(y/x)^2
>
> Z = 20*lg(x) + 10*lg(v)
>
> I'd factor it this way if x is greater than y. If y is larger, then factor

There's one more optimization that can be applied. Instead of computing
(1+(y/x)^2) and using that as input to the lg(), it'd make more sense to
compute (y/x) and create a new table that implements the function:

f(w) = lg(1+w^2)

This saves the squaring.

A comment about the division: the ratio y/x will be less than 1 ( or it
should be less than 1, if it's not then factor out y instead of x). If you
performed an 8-bit integer division, you'll get zero. You could perform a
16-bit/8-bit division and premultiply y by 0x100 (i.e. move it to the
upper byte of a 16-bit word). However a slightly more efficient division
can be found in the arctan routine:

http://www.dattalo.com/technical/software/pic/arctan.asm

Look for FRAC_DIV:, a "fractional division" routine.

Also, the coefficients in the above equations can be factored into the
tables. When all's said done, this equation should take less than 200
cycles to compute.

Scott

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv mitvma.mit.edu with SET PICList DIGEST in the body  On Sun, 16 Sep 2001, Scott Dattalo wrote:

> On Sun, 16 Sep 2001, David J Binnington wrote:
>
>
> David,
>
>
> You can re-write your equation like:
>
> Z = 10*lg(x^2 + y^2)...

This isn't the intial expression that was asked to be calculated.  It is not
x^2, but rather 2^x.  Actually, the correct equation is much easier to
calculate than the one you've been discussing.  Along the same lines as you
mentioned, the correct way to rewrite it is:

Z = 10*log(2^(x/10)+2^(y/10))
= 10*log(2^(x/10) (1+2^[(y-x)/10]))
= 10*log{2^(x/10)} + 10*log{1+2^[(y-x)/10]}
= x+10*log{1 + 2^[w/10]}

where w = y-x.  Notice that this is a subtraction, not a division.  That
makes life much easier.  For this expression, let y be the larger of your 2
input values.  Now you only need one table lookup for f(w) =
10*log{1+2^[w/10]} and an addition.  I doubt that you can code a division,
power, and log routine in 100 instructions, which is what the table will
occupy since w can be at most 100 if x & y are limited to 100.  Plus,
execution cycles will consist of a subtraction to calculate w (and possible
negation if x>y), a table lookup and an addition.

Kevin

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv mitvma.mit.edu with SET PICList DIGEST in the body  Olin, I am stuck with the values as they are.  I can scale them but thats

David

{Quote hidden}

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv mitvma.mit.edu with SET PICList DIGEST in the body  {Quote hidden}

Thanks Scott I will look at that.  I appreciate the help.  I am not a
complete novice with the PIC but this one is really stretching me.  I can't
help thinking there must be an easier way to add two non linear values!

David

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv mitvma.mit.edu with SET PICList DIGEST in the body   On Mon, 17 Sep 2001, Kevin Moll wrote:

> On Sun, 16 Sep 2001, Scott Dattalo wrote:
>
> > On Sun, 16 Sep 2001, David J Binnington wrote:
> >
> > > Can anybody give me a kick start with this?
> >
> > David,
> >
> >
> > You can re-write your equation like:
> >
> > Z = 10*lg(x^2 + y^2)...
>
> This isn't the intial expression that was asked to be calculated.  It is not
> x^2, but rather 2^x.

You're right. It would appear that not only do I not read the Off Topic
messages, I don't read the On Topic ones either!

{Quote hidden}

Or, you could choose to factor the larger of x and y then the difference
in the exponent would always be negative. The table only needs to be 16
entries (if linear interpolation is used).

Scott

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv mitvma.mit.edu with SET PICList DIGEST in the body  {Quote hidden}

Kevin, you are right.  I am just gathering information in my spare time for
a future project so haven't started to code yet.  I didn't notice that Scott
had mutated the expression.  Sorry Scott! ;-)

I am not sure if I completely follow your rearrangement above but if I can
do everything in one hit with a single table that would be excellent.  It
makes sense to pre-calculate as much as possible outside of the program.

The original expression is definitely Z = 10*log(2^(X/10)+2^(Y/10))

My first thoughts were along the lines of creating a 16-bit table containing
the result of 2^(X/10) for X=40 to 100 (using an index offset of 40). The
table values run from 16 to 1024.  An 8-bit table could be used instead with
the hi bytes calculated in line which might be more efficient.

The same table could also yield 2^(Y/10) since the range is the same.  Using
sixteen bit addition would then give me 2^(X/10)+2^(Y/10).  Z has to be
within the same range of 40 to 100 since the input X or Y values will have
to be limited by testing the result in Z.   I really wanted to avoid using a
log routine so I was toying with the idea of trying to use the same table in
reverse by using succesive approximation.  It all started to get very messy.

When I get a chance I will try your suggested method in Excel.  Any other
thoughts welcome!

Thanks

David

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  Thanks Kevin and Scott, your suggestions work fine using a single table. It
just needs a bit of fine tweaking now.

David

> {Original Message removed}

More... (looser matching)
- Last day of these posts
- In 2001 , 2002 only
- Today
- New search...