Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

RE: [AVR-Chat] Faster arithmetic

2005-06-15 by Paul Curtis

Peter, 

> > 
> >>In my application, I only wanted the most significant 16 
> bits. there 
> >>are two easy ways to shed them:
> >>
> >>w = ((long)x * y) / 65536;  //takes 782 cycles (toooo long at 16MHz)
> >>
> >>This seems to trigger a full divide with the compiler missing the 
> >>optimisation, so I gave it a clue:
> > 
> > Actually, the compiler is doing the correct thing in implementing a 
> > full divide.
> > 
> > Consider (1 * -1) / 65536.  That's -1L / 65536 which is 0.
> > 
> > 
> In those cases, CodeVision generates the following:
> 
>           ;     152 z = (1*-1)/65536;36
>            _0xA:
> 00014b e0e0      	LDI  R30,0
> 00014c 93e0 0169 	STS  _z,R30
> 00014e 93e0 016a 	STS  _z+1,R30
> 000150 93e0 016b 	STS  _z+2,R30
> 000152 93e0 016c 	STS  _z+3,R30
>           ;     153 z = -1L/65536;
> 000154 e0e0      	LDI  R30,0
> 000155 93e0 0169 	STS  _z,R30
> 000157 93e0 016a 	STS  _z+1,R30
> 000159 93e0 016b 	STS  _z+2,R30
> 00015b 93e0 016c 	STS  _z+3,R30
> 
> So it can spot optimisations - 

That's for constants, which any C compiler is *required* to evaluate at
compile time, not run time.  I merely point out that -1L/65535 != -1L >>
16.

> I am not really complaining, 
> just pointing out that it pays to look at what is going on. I 
> am sure it is quite correct in doing the divide. I just 
> expected the shortcut on first sight.
> 
> > 
> > Consider (1 * -1) >> 16.  That's -1L >> 16 which is still -1.
> 
> And CodeVision gets that right as you would expect but I am using 
> unsigned quantities

...but you're not, you've told the compiler that you're using signed
quantities, you said "long" not "unsigned long" in your code snippet.
If you has said "unsigned long" in the cast, the division by 65536 would
decay to a shift.

> > (Actually, there *is* a way to implement a signed divide by 
> a power of
> > two without using the clockwork method.)
> 
> What is that?

x /= 2**n can be coded using shifts like this:

if (x < 0)
  x += (2**n)-1;
x >>= n;

--
Paul Curtis, Rowley Associates Ltd  http://www.rowley.co.uk
CrossWorks for MSP430, ARM, AVR and (soon) MAXQ processors

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.