> Just in case the below wasn't explicit enough, the info below would be
> converted into C as follows:
>
> result = input / 125; // Original
> result = input / 128 + input / 8192 + input / 16384 + input / 262144;
> // To binary equivalant ( with 0.007% error)
> result = input >> 7 + input >> 13 + input >> 14 + input >> 18; //
> Using shifts rather than division (faster, same result)
>
> Slightly faster (since a one bit shift takes a full instruction cycle):
> temp = input;
> temp = temp >> 7;
> result += temp;
> temp = temp >> 6; // temp = input >> 13
> result += temp;
> temp = temp >> 1; // temp = input >> 14
> result += temp;
> temp = temp >> 4; // temp = input >> 18
> result += temp;
>
> This can be optimized further, but it only requires a total of 18
> shifts (whereas the previous version might have actually generated 52
> shifts) and a similar number of additions. Across a 48 bit number on
> an 8 bit processor this adds up...
>
> If you decide you only need 1% accuracy, then you only need the first
> two factors (128, 8192), and if you want 0.001% accuracy you need 6
> factors (128, 8192, 16384, 262144, 2097152, 8388608).
>
> -Adam
>
> On Wed, Apr 29, 2009 at 10:38 AM, M. Adam Davis <
KILLspamstienmanKILLspam
gmail.com>
> wrote:
> > This should give you what you need - you can turn a division into a
> > sum of several binary divisions:
> >
> > piclist.com/techref/method/math/divconst.htm
> >
> > There is an online code generator here, though it only goes up to 32
> > bits, but you probably don't care about the code generated, just the
> > binary division factors:
> > www.piclist.com/techref/piclist/codegen/constdivmul.htm
> >
> > 1/125 = 0.008, which happens to be very close to:
> >
> > ; ALGORITHM:
> > ; Clear accumulator
> > ; Add input / 128 to accumulator
> > ; Add input / 8192 to accumulator
> > ; Add input / 16384 to accumulator
> > ; Add input / 262144 to accumulator
> > ; Move accumulator to result
> > ;
> > ; Approximated constant: 0.00799942, Error: 0.00724792 %
> >
> >
> www.piclist.com/cgi-bin/constdivmul.exe?Acc=ACC&Bits=32&endian=little&Const=.008&ConstErr=0.05&Temp=TEMP&cpu=pic16
> >
> > You can change the "ConstErr=0.05" to a finer value to reduce the error
> further.
> >
> > -Adam
> >
> > On Wed, Apr 29, 2009 at 3:14 AM, William "Chops" Westfield
> > <
RemoveMEwestfwTakeThisOuT
mac.com> wrote:
> >> I want to calculate:
> >>
> >> (ticks * <microsecondsPerTick>) / 1000
> >>
> >> to return the number of milliseconds elapsed based on a count
> >> maintained by a timer ISR. microsecondsPerTick is a nice constant
> >> number like 1024 or 2048, so the multiplication becomes a shift, and
> >> factoring out twos I get:
> >>
> >> (ticks * (microsecondsPerTick/8)) / 125
> >>
> >> "ticks" is at least 40 bits, however, and the multiplication MUST NOT
> >> OVERFLOW (been there, trying to fix that!), so I'm looking at at at
> >> least a 48bit intermediate value.
> >>
> >> It would be nice if the code were in C. Avr gcc, in particular.
> >> There are 8, 16, 32, and even 64 bit math functions available, but of
> >> course they're *C*, so they don't let you actually do mixed-sized
> >> math, nor are they likely to optimized
> >>
> >> The code is not particularly time critical, but it would be nice if it
> >> were as small and fast as possible (using 64bit long longs seems
> >> excessive.)
> >>
> >> Thoughts? Any pointers to mixed-size C math functions in general? In
> >> principle, I think I understand how to do this, but ... Is there a
> >> way to take advantage of the constant? Of 125 in particular? (lots
> >> of one bits there...)
> >>
> >> Thanks
> >> Bill W
> >>
> >> --