Last active
January 11, 2018 14:17
-
-
Save lou1306/72cf7473b5df4bf182d4c43d53c7aeb4 to your computer and use it in GitHub Desktop.
Packing two integers inside a single `int`
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
#include "stdio.h" | |
#include "stdlib.h" | |
#define W 15 // Bit-Width of tuple elements (Up to 15 is fine) | |
const int MASK = (1U << W) - 1; | |
const int MASK2W = (1U << 2*W) - 1; | |
const int m = 1U << (W - 1); | |
/** | |
* @brief Trim n into bit-width W. | |
* @return A two's complmenent, W-bit representation of n. | |
*/ | |
inline int trim(int n) { | |
n = n >= 0 ? abs(n) : ~abs(n) + 1; | |
return n & MASK; | |
} | |
/** | |
* @brief Extend the sign of x | |
* @details see: https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend | |
* @param x A two's complement, W-bit representation of an integer | |
* @return an int containing the same integer represented by x | |
*/ | |
inline int signExtend(int x) { | |
return ((x & MASK) ^ m) - m; | |
} | |
/** | |
* @brief Pack x and y into a tuple. | |
*/ | |
int packTuple(int x, int y) { | |
int tup = trim(y) | (trim(x) << W); | |
tup &= MASK2W; | |
return tup; | |
} | |
int getX(int tup) { | |
return signExtend(tup >> W); | |
} | |
int getY(int tup) { | |
return signExtend(tup); | |
} | |
/** | |
* @brief Check that a tuple has been packed correctly | |
* @details [long description] | |
* | |
* @param tup The tuple to check | |
* @param expectedX Expected first element of the tuple | |
* @param expectedY Expected second element of the tuple | |
* @return 1 if tup == (expectedX, expectedY); 0 otherwise | |
*/ | |
int testTuple(int tup, int expectedX, int expectedY) { | |
return (expectedX == getX(tup) && expectedY == getY(tup)); | |
} | |
void printTuple(int tup) { | |
int x = getX(tup); | |
int y = getY(tup); | |
printf("t: %x (x: %i, y:%i)\n", tup, x, y); | |
} | |
/** | |
* @brief Returns the elemwnt-wise sum of two tuples | |
* @return The tuple `(t1.x + t2.x, t1.y + t2.y)` | |
*/ | |
int sum(int t1, int t2) { | |
return packTuple(getX(t1)+getX(t2), getY(t1)+getY(t2)); | |
} | |
/** | |
* @brief Test that everything works | |
* @details This will test that all possible tuples are correctly packed and | |
* unpacked. If something goes wrong, it will print some data about the tuple | |
* that failed to unpack. | |
*/ | |
int main(void) { | |
const int MAXELEM = (1U << (W-1)); | |
for(int x = -MAXELEM+1; x < MAXELEM; ++x) { | |
for(int y = -MAXELEM+1; y < MAXELEM; ++y) { | |
int t = packTuple(x, y); | |
if (!testTuple(t, x, y)) { | |
printf("ERROR x: %i, y: %i\n", x, y); | |
printTuple(t); | |
return 1; | |
} | |
} | |
// printf("%i\n", x); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment