Thread: absolute value of a double

1. absolute value of a double

I would like an efficient way to get the positive value of a double.
The obvious way would be:

Code:
```double absolute(double number)
{
if (number < 0)
return -number;
else
return number;
}```
but I would like something which is faster. I have considered the fact of using a mask on the number (so its first bit - the sign bit according to the IEEE 754 standard - would become 0) but that simply doesn't work on double number. The & doesn't work at all on double numbers.

2. Where can I find what exactly does?
The best that I have found till now is:
Code:
```  inline float
fabs(float __x)
{ return __builtin_fabsf(__x); }

inline long double
fabs(long double __x)
{ return __builtin_fabsl(__x); }

template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
fabs(_Tp __x)
{ return __builtin_fabs(__x); }```
from the cmath.h file, but it wasn't really helpful.

3. Err... I think you got your tongue twisted. It's math.h for C and cmath for C++, no cmath.h. (except maybe pre-standard headers, but I'm not sure about that.)

For standards:

Looking in implementations' implementations for information on what a function is guaranteed to do is not a good idea because the implementation of your implementation may vary from implementation to implementation.

4. You are looking for the absolute value for a real number?

5. yes.

6. I see. I was just wondering.

7. So, the moral of this story is that there is no way to apply a mask on an double. Right?
I tried to cast it and then use a mask but it doesn't work because some digits are truncated.

8. In case you need to apply a mask, you can do:
Code:
```double d = 1.0;
unsigned long long* x = (unsigned long long*)&d;
*x |= 0x20;```
Just beware that a double isn't an integral type, so you won't see "1" or anything in *x.

9. Code:
```double absolute(double number)
{
printf("%f ", number);
unsigned long long* x = (unsigned long long*)&number;
*x &= 0x7fffffff;

number = *(double *)x;
printf("%f \n", number);
return number;
}```
It doesn't work. It always returns 0.

10. Code:
`    number = *(double *)x;`
You should not need to do that, since x is a pointer to the original double, the original value is affected. Do not assign.
The problem is also that a mask designed for integers won't work for doubles, since they are clearly different.
To use masks on doubles, you'll have to read about how floating point works. It's a little outside my area, though.

11. it doesn't work because your mask
Code:
`0x7fffffff;`
is a little too short ( it's a long literal ).
Kurt

12. Thanks!
The solution is:

Code:
```double absolute(double number)
{
//printf("&#37;f ", number);
unsigned long long* x = (unsigned long long*)&number;
*x &= 0x7fffffffffffffff;

number = *(double *)x;
//printf("%f \n", number);
return number;
}```
I have run some test and it is faster than the other implementation. The jumps add a complexity because compiler can't decide efficiently what is the next instruction to execute. It's still slower than the implementation of the standard library, though.

13. Again,
Code:
`number = *(double *)x;`
This is not necessary!

14. Indeed. You are right. Sometimes I am such an idiot.
My best try so far, still slower than the standard implementation:

Code:
```double inline absolute(double number)
{
//printf("&#37;f ", number);
unsigned long long* x = (unsigned long long*)&number;
*x &= 0x7fffffffffffffff;

//printf("%f \n", number);
return number;
}```

Popular pages Recent additions