![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
Boundary checking on signed value using bit test |
Posted: Tue May 25, 2010 5:49 pm |
|
|
I'm trying to do a fast boundary check on a value that keeps increasing with every iteration of the loop. The magnitude that the value increases with each iteration is fixed. So I should be able to do the following to keep the accumulating_number variable from going much above 8192 and below -8192:
Code: | if(!bit_test(accumulating_number,13)) accumulating_number += error; |
Both accumulating_number and error are declared as signed int16's.
But, when error is consistently negative, it grows well beyond the -8192. I haven't seen any values less than -32768, but they are almost always -32xxx.
As long as I do the following code, it works fine (but the above is *much* faster):
Code: |
accumulating_number += error;
if(accumulating_number > 8192) accumulating_number = 8192;
else if(accumulating_number < -8192) accumulating_number = -8192;
|
Any ideas? I'm baffled. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 25, 2010 8:54 pm |
|
|
If you're in doubt about how something works, make a little test program
to study the boundary conditions. This code will do your negated bit 13
test, and step through values that are near to 8192 and -8192. You can
run it in MPLAB simulator, with "UART1" sending the printf output to the
MPLAB Output Window so you can see the results:
Quote: |
8190 (1ffe): Negated Bit 13 test = 1
8191 (1fff): Negated Bit 13 test = 1
8192 (2000): Negated Bit 13 test = 0
8193 (2001): Negated Bit 13 test = 0
8194 (2002): Negated Bit 13 test = 0
-8190 (e002): Negated Bit 13 test = 0
-8191 (e001): Negated Bit 13 test = 0
-8192 (e000): Negated Bit 13 test = 0
-8193 (dfff): Negated Bit 13 test = 1
-8194 (dffe): Negated Bit 13 test = 1
|
Test program:
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main(void)
{
signed int16 acc_number;
for(acc_number = 8190; acc_number < 8195; acc_number++)
{
printf("%ld (%lx): ", acc_number, acc_number);
printf("Negated Bit 13 test = %u", !bit_test(acc_number,13));
printf("\r");
}
printf("\r");
for(acc_number = -8190; acc_number > -8195; acc_number--)
{
printf("%ld (%lx): ", acc_number, acc_number);
printf("Negated Bit 13 test = %u", !bit_test(acc_number,13));
printf("\r");
}
while(1);
}
|
How to use "UART1" in MPLAB:
http://www.ccsinfo.com/forum/viewtopic.php?t=40045 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Wed May 26, 2010 2:15 am |
|
|
PCM programmer has shown how to 'see' what is happening. The reason, is in how -ve numbers are stored. Remember -1, is 0xFFFF.
Your test can be done in a number of ways:
Code: |
accumulating_number += error;
if ((bit_test(accumulating_number,15)?\
bit_test(accumulating_number,13):!bit_test(accumulating_number,13))
|
Or:
Code: |
if (!(bit_test(accumulating_number,13)^bit_test(accumulating_number,13)))
|
Or (obviously), performing the test on the abs value.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
evsource
Joined: 21 Nov 2006 Posts: 129
|
|
Posted: Wed May 26, 2010 9:14 am |
|
|
Ttelmah wrote: | PCM programmer has shown how to 'see' what is happening. The reason, is in how -ve numbers are stored. Remember -1, is 0xFFFF. |
Thanks Ttelmah and PCM programmer. Ttelmah, you weeded out my innocence (stupidity might be an interchangeable word here! ). I had the mistaken idea that the negative representation of the number was identical to the positive number, only with the sign bit flipped. Back to two's compliment 101.
I see my mistake now. As you said, easy enough to fix:
Code: |
if((!bit_test(accumulating_number,15) && !bit_test(accumulating_number,13)) || (bit_test(accumulating_number,15) && bit_test(accumulating_number,13)) ) accumulating_number += error;
|
Probably some ways to optimize further for speed, if it's known whether the error will tend more towards being positive or negative. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|
Powered by phpBB © 2001, 2005 phpBB Group
|