Last active
July 28, 2016 03:36
-
-
Save n-soda/93565d365d987a134a88 to your computer and use it in GitHub Desktop.
min()/max() implementation without using conditional branch instruction
This file contains hidden or 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
| /* | |
| * max()/min() implementation without any conditional branch instruction. | |
| * basic idea from: | |
| * https://twitter.com/vivisuke/status/539563588332310528 | |
| * http://vivi.dyndns.org/blog/archives/306 | |
| * | |
| * countermeasure against signed integer overflow by n-soda @ github | |
| * | |
| * NOTE: | |
| * this program is NOT truly portable, | |
| * because it is implementation-defined behavior how ">>" operator works | |
| * against a signed integer. | |
| * | |
| * This code does not use conditional branch with legacy CPUs which do not | |
| * have an instruction like x86 SETcc instruction, but for modern CPUs | |
| * which have a SETcc equivalent, the following way which is described in | |
| * http://graphics.stanford.edu/~seander/bithacks.html | |
| * is better: | |
| * maximum: return x ^ ((x ^ y) & -(x < y)); | |
| * minimum: return y ^ ((x ^ y) & -(x < y)); | |
| * and branch instructions don't have to be avoided with such legacy CPUs ;-) | |
| * | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <limits.h> | |
| #define INT_BIT (sizeof(int) * CHAR_BIT) | |
| int int_maximum(int a, int b) | |
| { | |
| int diff = a - b - INT_MIN; | |
| int a_lt_b = | |
| (((a - b) ^ ((a ^ b) & (a ^ (a - b)))) & (a | diff | -diff)) | |
| >> (INT_BIT - 1); | |
| return (a & ~a_lt_b) | (b & a_lt_b); | |
| } | |
| int int_minimum(int a, int b) | |
| { | |
| int diff = a - b - INT_MIN; | |
| int a_lt_b = | |
| (((a - b) ^ ((a ^ b) & (a ^ (a - b)))) & (a | diff | -diff)) | |
| >> (INT_BIT - 1); | |
| return (a & a_lt_b) | (b & ~a_lt_b); | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| int a, b; | |
| if (argc != 3) { | |
| fprintf(stderr, "Usage: %s <value-1> <value-2>\n", argv[0]); | |
| return 1; | |
| } | |
| a = atoi(argv[1]); | |
| b = atoi(argv[2]); | |
| printf("maximum(%d, %d) = %d\n", a, b, int_maximum(a, b)); | |
| printf("minimum(%d, %d) = %d\n", a, b, int_minimum(a, b)); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment