• ### Popular Now

• 10
• 9
• 13
• 10
• 18

#### Archived

This topic is now archived and is closed to further replies.

# How fast is the abs() function?

This topic is 5996 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

##### Share on other sites
abs() may be implemented as a macro; the C standard library provides both function and macro versions. For most uses, the macro version is more than sufficient, and it looks like this:
#define abs(x) ((x > 0) ? x : -x)

Given that expansion, I think your first version of InRange() would be faster (fewer operations).

##### Share on other sites
Thanks, I was thinking maybe the abs function was done in assembly and simply sets the signed bit to off, which would be dang quick compared to doing some greater than / less than checking.

Hmm in fact maybe i could even just do a quick bit shift to clear the sign bit? Is the leading bit on a float the sign bit? If so i could shift it left once, clearing the leading bit to zero, then shift it back right, and the number would then be positive? Something like:

x << 1;
x >> 1;

I'll also try the macro way and see if that gives any improvement.

Edited by - nPawn on October 19, 2001 1:36:53 PM

##### Share on other sites
quote:
Original post by nPawn
x << 1;
x >> 1;

x &= (1 << 31);

I'm too preoccupied to think what that compiles to, but it's clearer what you're trying to do (and a single AND is better than 2 shifts).

Edit: and don't worry about the shift. Since both operands are constants, the compiler will replace that with the literal equivalent at compile time (provided your compiler is set to optimize.)

Edited by - Oluseyi on October 19, 2001 2:05:06 PM

##### Share on other sites
The absolute value of a float (ie 32-bit floating point number in IEEE) can be found like this in C/C++:

  #define FLOAT_BITS(f) (*(int*)&(f))inline float fabs(float f){ return FLOAT_BITS(f) & 0x7FFFFFFF; }

##### Share on other sites
Oluseyi: It would actually be:

x &= ~(1 << 31);

Or, to make it easier:

x &= 0x7fffffff;

But clearing the MSB isn''t going to help you at all if you''re dealing with integers.

Integers use a two''s complement signed implementation, so clearing the MSB is going to be fine for positive numbers, but for negative numbers, you''ll just end up with a completely unrelated positive number.

-1 = 0xFFFFFFFF

With your code, you''d end up turning that into 0x7FFFFFFF which most certainly is not 1

I''m afraid you''ll have to do a comparison. There is a tricky way of doing it in assembly without a comparison, provided you''re working in 16-bit real mode:

;
; Input: AX = Number
; Output: AX = Absolute value
; Trashed: DX
;

cwd
xor ax, dx
sub ax, dx

That''s a trick I picked up from Abrash''s graphics book. However, he mentions this code is actually slower on 486s than a TEST and jump. So I guess you''ll have to use

test eax, eax
jns short .dont_negate
neg eax
.dont_negate
...

If there''s a particularly fast way of doing a 32-bit absolute value in assembly (faster than TEST+JNS), please let me know! (Try emailing trzy@mailandnews.com if you can.)

---
Bart

##### Share on other sites
quote:
Original post by trzy
Oluseyi: It would actually be:

x &= ~(1 << 31);

Or, to make it easier:

x &= 0x7fffffff;

Thanks. Missed that.

I did think about the two''s complement aspect of things, but I''m too lazy to immediately come back and rectify the code. I just did this problem last week in SPARC assembly...

Thanks. That''s why I like forums; someone else will spot and correct your mistakes (hopefully).