Purpose of bitwise OR of an integer with its negative

瘦欲@ 提交于 2019-12-23 12:25:31

问题


I was curious about the implementation and representation of NaN in both IEEE single- and double-precision floating points, and I found this implementation of an "is NaN" function. Namely:

int isnan(double x)
{
    int32_t hx,lx;

    // Move lower 32 bits of double to lx, higher 32 to hx.
    EXTRACT_WORDS(hx,lx,x);

    // Remove sign bit, since -NaN and NaN are both NaN.
    hx &= 0x7fffffff;

    // Equivalent to hx |= (lx != 0).
    hx |= (u_int32_t)(lx|(-lx))>>31;

    // Difference is negative iff (hx & 0x7ff00000) == 0x7ff00000 and (hx & 0x000fffff) != 0.
    hx = 0x7ff00000 - hx;
    return (int)((u_int32_t)(hx))>>31;
}

I didn't understand the purpose of (lx|(-lx)) >> 31, and after failing to reason it out in my head, I tested it on all integers, and found it results in 0 for lx = 0 and 1 otherwise.

The only reasons I could come up with are that perhaps using (lx != 0) instead was not possible due to some C standard not defining what integer value is assigned to true operations (e.g. not guaranteed to be 1 for true) or that perhaps != is slower than the negative-or-and-bit-shift. Otherwise, I'm stumped.

For reference, the code I used to try all integers, in case of errors.

#include <stdio.h>
#include <stdint.h>
int main(void) {
        int32_t i = 0;
        do {
                if (((uint32_t)(i | (-i)) >> 31) == 0)
                        printf("%d\n", i); // prints only 0
        } while (i++ != 0xFFFFFFFF); // overflows to -max_int and then climb to -1
        return 0;
}

回答1:


The expression (u_int32_t)(lx|(-lx))>>31 is equivalent to lx==0? 0:1.

However, with lx==0? 0:1, you are imposing a branch operation into the object code.

This might yield reduced performance in comparison with a couple of bit-wise operations.

It really depends on the underlying HW architecture as well as the designated compiler at hand.

But it will for sure lead to inconsistent performance, depending on branch-prediction heuristics.

The running time of (u_int32_t)(lx|(-lx))>>31 is guaranteed to be identical on every execution.



来源:https://stackoverflow.com/questions/25905263/purpose-of-bitwise-or-of-an-integer-with-its-negative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!