The Ultimate Fast Absolute Value
Started by blueone, Jun 10 2006 08:38 AM
12 replies to this topic
#1
Posted 10 June 2006 - 08:38 AM
Bitwise operation--------------------
From Wikipedia, the free encyclopedia
In computer programming, a bitwise operation operates on one or two bit patterns or binary numerals at the level of their individual bits. On many computers, bitwise operations are slightly faster than addition and subtraction operations and significantly faster than multiplication and division operations.
I dont know if there was already existing fast absolute value in this forum but Id like to share my own :lol: .
This is absolute value for short int. It will return a new value as unsigned short.
unsigned short abss(ushort g)
{
if (g&32768u)
return 32768u-(g&32767u);
return (g);
}
This is absolute value for int.
unsigned int absi(int g)
{
if (g&2147483648u)
return 2147483648u-(g&2147483647u);
return (g);
}
This is absolute value for long int.
unsigned long int absl(long int g)
{
if (g&9223372036854775808llu)
return 9223372036854775808llu-(g&9223372036854775807llu);
return (g);
}
Is this what you are looking for? :lol:
float absf(float g)
{
unsigned int *gg;
gg=(unsigned int*)&g;
*(gg)&=2147483647u;
return g;
}
Another one :yes:
double absd(double g)
{
unsigned long int *gg;
gg=(unsigned long int*)&g;
*(gg)&=9223372036854775807llu;
return g;
}
Hope you like its performance :worthy: :sneaky: :lol:
From Wikipedia, the free encyclopedia
In computer programming, a bitwise operation operates on one or two bit patterns or binary numerals at the level of their individual bits. On many computers, bitwise operations are slightly faster than addition and subtraction operations and significantly faster than multiplication and division operations.
I dont know if there was already existing fast absolute value in this forum but Id like to share my own :lol: .
This is absolute value for short int. It will return a new value as unsigned short.
unsigned short abss(ushort g)
{
if (g&32768u)
return 32768u-(g&32767u);
return (g);
}
This is absolute value for int.
unsigned int absi(int g)
{
if (g&2147483648u)
return 2147483648u-(g&2147483647u);
return (g);
}
This is absolute value for long int.
unsigned long int absl(long int g)
{
if (g&9223372036854775808llu)
return 9223372036854775808llu-(g&9223372036854775807llu);
return (g);
}
Is this what you are looking for? :lol:
float absf(float g)
{
unsigned int *gg;
gg=(unsigned int*)&g;
*(gg)&=2147483647u;
return g;
}
Another one :yes:
double absd(double g)
{
unsigned long int *gg;
gg=(unsigned long int*)&g;
*(gg)&=9223372036854775807llu;
return g;
}
Hope you like its performance :worthy: :sneaky: :lol:
#2
Posted 10 June 2006 - 09:12 AM
I hate to be the one to tell you but these things are well known. It's cool though that you found them on your own! :yes:
A typically faster and more importantly cleaner way to compute absolute value is:
For floating point we can also use the slightly nicer hexadecimal notation:
A typically faster and more importantly cleaner way to compute absolute value is:
inline int abs(int x)
{
return (x > 0) ? x : -x;
}
On most platforms this compiles into code without branches (no jumps) and computing -x takes just one clock cycle.For floating point we can also use the slightly nicer hexadecimal notation:
inline float abs(float x)
{
int y = (int&)x & 0x7FFFFFFF;
return (float&)y;
}
#3
Posted 10 June 2006 - 10:54 AM
Nick: unfortunately, your abs float code performs terrible on the xbox360 for example, as it requires the variable to be stored to memory. This has massive stalls.
And why is fabs slow anyway? The cpu only has to set a single bit to 1. Is it the long path to the FPU? Or is it that fabs itself isn't slow, but the C runtime function around it that is?
Also, here is an abs(int) without conditional code:
a shift, a xor and an add.
And why is fabs slow anyway? The cpu only has to set a single bit to 1. Is it the long path to the FPU? Or is it that fabs itself isn't slow, but the C runtime function around it that is?
Also, here is an abs(int) without conditional code:
int abs(int value)
{
static const int INT_BITS = sizeof(int) * CHAR_BIT;
int topbitreplicated = value >> (INT_BITS - 1);
return (value ^ topbitreplicated) - topbitreplicated;
}
a shift, a xor and an add.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.
-
Currently working on: the 3D engine for Tomb Raider.
#4
Posted 10 June 2006 - 06:24 PM
.oisyn said:
Nick: unfortunately, your abs float code performs terrible on the xbox360 for example, as it requires the variable to be stored to memory. This has massive stalls.
Quote
And why is fabs slow anyway? The cpu only has to set a single bit to 1. Is it the long path to the FPU? Or is it that fabs itself isn't slow, but the C runtime function around it that is?
Quote
Also, here is an abs(int) without conditional code:
a shift, a xor and an add.
int abs(int value)
{
static const int INT_BITS = sizeof(int) * CHAR_BIT;
int topbitreplicated = value >> (INT_BITS - 1);
return (value ^ topbitreplicated) - topbitreplicated;
}
a shift, a xor and an add.
cdq xor eax, edx sub eax, edxcdq is equivalent to 'mov edx, eax; sar edx, 31'. This is also what Visual C++ 2005 uses when using the math.h abs() function.
#5
Posted 28 June 2006 - 11:48 AM
Nick said:
For floating point we can also use the slightly nicer hexadecimal notation:
inline float abs(float x)
{
int y = (int&)x & 0x7FFFFFFF;
return (float&)y;
}
#6
Posted 28 June 2006 - 01:49 PM
WatsonLadd said:
No we cannot. IEEE floating point does not set the internal representation in any way, shape or form. And you rounded.
But feel free to elaborate... :huh:
#7
Posted 29 June 2006 - 12:12 AM
WatsonLadd said:
IEEE floating point does not set the internal representation in any way, shape or form.
#8
Posted 29 June 2006 - 04:05 AM
hi,
in x86 asm, for a int, you can do
but dunno if its fast enought
jmgk
in x86 asm, for a int, you can do
btr eax,31
but dunno if its fast enought
jmgk
#9
Posted 29 June 2006 - 04:12 AM
Unfortunately, that doesn't work. You can't just reset the sign bit as numbers are stored in two's complement format.
reedbeta.com - developer blog, OpenGL demos, and other projects
#10
Posted 29 June 2006 - 11:16 AM
Aliasing = bad.
Use unions.
Use unions.
#11
Posted 29 June 2006 - 06:25 PM
Reedbeta said:
You can't just reset the sign bit as numbers are stored in two's complement format.
Or did I misunderstand you?
#12
Posted 29 June 2006 - 06:39 PM
Reedbeta was answering to jmgk post, not yours.
#13
Posted 29 June 2006 - 10:00 PM
Yes. He claimed you could do it by just resetting bit 31 for integers. That would certainly work for an IEEE float stored in an integer register though. Which is exactly what Nick's code sample does.
reedbeta.com - developer blog, OpenGL demos, and other projects
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users











