|
|
View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
abs() function ... is there a more efficient way? |
Posted: Thu Sep 24, 2009 1:37 pm |
|
|
I need to get the absolute value of a signed long that is known to be negative. The abs() function does this in several instructions, when it seems there is a much easier way to do it (unless I'm doing something wrong).
Code: |
raw_temperature_reading = abs(sum_of_all_good);
// take the two's compliment of the negative number to give the positive equivalent
sum_of_all_good ^= 0xFFFF;
sum_of_all_good++;
|
The list file:
Code: |
.................... raw_temperature_reading = abs(sum_of_all_good);
01776: MOVFF 274,03
0177A: MOVF x73,W
0177C: BTFSS x74.7
0177E: BRA 1790
01780: MOVLW 00
01782: BSF FD8.0
01784: SUBFWB x73,W
01786: MOVWF 00
01788: MOVLW 00
0178A: SUBFWB x74,W
0178C: MOVWF 03
0178E: MOVF 00,W
01790: MOVWF x6F
01792: MOVFF 03,270
....................
.................... // take the two's compliment of the negative number to give the positive equivalent
.................... sum_of_all_good ^= 0xFFFF;
01796: MOVLW FF
01798: XORWF x73,F
0179A: XORWF x74,F
.................... sum_of_all_good++;
0179C: INCF x73,F
0179E: BTFSC FD8.2
017A0: INCF x74,F
|
Am I doing something wrong? Is it really that much more efficient to do it the second way, i.e. not using abs()? |
|
|
Ttelmah Guest
|
|
Posted: Thu Sep 24, 2009 2:46 pm |
|
|
The 'point' of the ABS function, is that it returns the positive value, for both positive, and negative inputs. If you _know_ the value is -ve, then just use:
-sum_of_all_good
The compiler does this using just two comf instructions, followed by the increment (and carry if needed), using five instructions. One better than the XOR version.
Best Wishes |
|
|
evsource
Joined: 21 Nov 2006 Posts: 129
|
|
Posted: Thu Sep 24, 2009 2:58 pm |
|
|
Ttelmah wrote: | The 'point' of the ABS function, is that it returns the positive value, for both positive, and negative inputs. If you _know_ the value is -ve, then just use:
-sum_of_all_good
The compiler does this using just two comf instructions, followed by the increment (and carry if needed), using five instructions. One better than the XOR version.
|
Very good, thank you!
I'm taking 6 temperature measurements (can be positive or negative celsius), tossing out the high and the low (eliminate the most likely noise candidates), then averaging. Here's my implementation of what we just discussed to perform the averaging (BTW, "sum_of_all_good" is the summation of all the recorded values except the tossed high and low):
Code: |
if(sum_of_all_good >= 0) temperature = sum_of_all_good >> 2;
else {
-sum_of_all_good;
temperature = sum_of_all_good >> NTS_PWR2;
-temperature;
}
|
One final question - is the compiler smart enough to handle the sign bit for math operations involving int8's and int16's? For example, if I have my temperature values stored as signed int8's, and sum them into my signed int16 "sum_of_all_good", will the sign come out right if the int8 values are mixed between positive and negative in the int16 variable? (I know I can try this and see, but thought I'd ask in case someone else ever has the question) |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Thu Sep 24, 2009 4:56 pm |
|
|
If you could do the summing and averaging with the raw A/D readings before converting them to temperatures you wouldn't have to worry about signs. Of course that depends on where the temperature data is coming from, and if the A/D count vs temperature is linear over the range of readings in any one set of samples. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
barryg
Joined: 04 Dec 2006 Posts: 41
|
|
Posted: Thu Sep 24, 2009 5:37 pm |
|
|
Um...those statements like will compile, because C allows any statement to evaluate to a number. But it won't change the value! I tested this and the compiler simply leaves that line out. You have to have an assignment, like Code: | sum_of_all_good = -sum_of_all_good; |
Barry |
|
|
|
|
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
|