Author Message
Ttelmah

Joined: 11 Mar 2010
Posts: 18602

Scaled integer maths Posted: Tue Apr 21, 2020 1:41 am OK.
In the forum you will quite often have the 'old hands' saying 'use integer
maths'. What is this about?. Why?.

So lets start with a very basic design. A PIC 18F4520, used as a 0 to 5v
voltmeter. Sending the value to the serial port.

Two solutions. The first the 'obvious' one. Just use fp maths:

Now this merrily goes off and prints the voltage on the AN0 input
as n.nnnv every half a second. Perfect solution?.

But is it?.

The first thing to note is the size. Here 1670 bytes. Then run the code
and test how long it takes to do the maths, and print the result. 24.4mSec.

Now compare with this:
 Code: //Same setup code void main(void) {    int32 volts;    setup_ADC_ports(AN0, VSS_VDD);    setup_adc(ADC_CLOCK_DIV_16); //Read the data sheet for this. Here the Tad must be 0.7 to 25uSec //So from 16MHz, /16 gives 1uSec. Ideal.    set_adc_channel(0); //Now the ADC needs time to 'acquire' the signal. This can be programmed //as a multiplier from this clock. However With the long delays in the loop //I'm not using this.    fprintf(PC,"Awake\n");    while (TRUE)    {        delay_ms(500);        volts=(int32)read_adc()*5000/1024;        fprintf(PC,"Reading %5.3lwv\n",volts);        delay_cycles(1);    }  }

Now the first interesting thing is the code is about half the size (818 bytes).
Then it is faster. Only a little, but about 450uSec in total.

So what is going on?.

The compiler is very intelligent. On the sum:

It pre-solves the right hand half of this, and turns it into a single
multiplication by 0.0048828125. So this sum takes just 222uSec.

On the equivalent integer sum, this can't be pre-solved like this so it
stays as a multiplication then division. So actually ends up taking
slightly longer. However then there are the multiple
divisions to generate the digits in the printf. These take 412uSec
each in the floating point version, while only 298 in the integer
version. So at the end there is a total saving of nearly 0.5mSec
in speed. The total output takes just under 24mSec as given.
The saving is much more noticeable if you output the results to a
string, rather than delaying for the serial. It is the serial delays
that are giving much of the time involved here.

For this you expect to see 2.5v. For the float version, we have:

512*5 = 2560
then
2560/1024 = 2.5

Exactly right.

Now the integer version:

512*5000 = 2560000
then
2560000/1024 = 2500

which the %w format displays as 2.500

Again exactly right.

So the key here is that if instead of using floating point values like
x.xxv, you work in smaller units and use integers, you can save a
lot of space, and significant time. Here I'm doing the sum in 'integer mV'.
Thousandths of a volt, and can use integer numbers of these.

Key thing is that to keep in 'integer' the maths used must multiply
first. If you tried instead to use /1024 earlier in the sum, data would be
lost. So a little care is needed.
There is also another factor, which is accuracy. An int32 gives over 9
usable digits. A fp value only just over 6. So values are actually more
accurate processed this way.

So, think about it, when designing your code... This is a link to a thread in the main forum, where using this for a
more complex sum is discussed:

<http://www.ccsinfo.com/forum/viewtopic.php?t=56091&postdays=0&postorder=asc&start=0>

This raises the next important part to this.

On an unsigned integer number, the following divisions can be done
really quickly by simply 'shifting' the value:
/2, /4, /8, /16, /32, /64, /256 and so on.
In fact /256 and /65536 can be done even faster by just taking the
required bytes out of the result.
In this thread I do the integer equivalent of *0.48828125, by just
multiplying by 32000, and then taking the upper 16bits of the result.
This is several times faster and smaller. So again. Think about it... Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT - 6 Hours Page 1 of 1

 Jump to: Select a forum Software----------------General CCS C DiscussionCode LibraryEZ App LynxBest OfKnown Issues Hardware----------------CCS ICD / Mach X / Load-n-Go
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum