Last active
October 17, 2021 07:49
-
-
Save airglow923/fdb4727c2c491e7b1d68c20b7b72a281 to your computer and use it in GitHub Desktop.
Different ways to get the parity flag in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* As shown below, this code is not meant for getting the parity of a number; | |
* rather, it checks the parity flag. The reason is that the parity flag only | |
* represents whether the least significant byte has odd or even number of set | |
* bits. So, it should not be used to check the parity of a number in practice | |
* unless the number is one byte long. | |
* | |
* Having said that, an implementation-defined function by Clang and GCC for | |
* parity computation, __builtin_parity(x), returns 0 if x has even set bits and | |
* 1 if odd, which is the opposite of the parity flag. That is the reason why | |
* the code below applies NOT to the return value of __builtin_parity. | |
*/ | |
#include <stdint.h> | |
#if defined(__GNUC__) || defined(__clang__) | |
int | |
parity1(int64_t n) { | |
return !__builtin_parity(n); | |
} | |
#endif | |
#if defined(__i386) || defined(_M_IX86) | |
int | |
parity2(int64_t n) { | |
int tmp; | |
asm("cmp $0, %[n]\n\t" | |
"lahf\n\t" | |
"and $1024, %[tmp]" | |
: [tmp] "=r"(tmp) | |
: [n] "r"(n)); | |
return tmp; | |
} | |
#if defined(__SSE4_2__) || defined(__AVX__) || defined(__POPCNT__) | |
int | |
parity3(int64_t n) { | |
int64_t tmp; | |
asm("popcntq %[n], %%rax\n\t" | |
"andq $1, %[tmp]" | |
: [tmp] "=r"(tmp) | |
: [n] "r"(n)); | |
return !tmp; | |
} | |
#endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment