Alright, so the Stockfish project has this chunk of code, which allows storing two ints (which are expected to between ~[-16000, 16000]
EDIT: I forgot the mention, the whole purpose of this is so we can add together two ints at a time. IE
a1+a2,b1+b2 = Decode(Encode(a1,b1) + Encode(a2,b2))
constexpr int make_score(int mg, int eg) {
return (int)((unsigned int)eg << 16) + mg;
}
inline int eg_value(int s) {
union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
return (int)eg.s;
}
inline int mg_value(int s) {
union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
return (int)mg.s;
}
I would like to convert this to C. Obviously I can skip out on the inline and constexpr qualifiers. However, inline union definitions are not allowed. Additionally, I would prefer not to use a union, as it seems out of place IMO.
Here is what I have in C
#define MakeScore(mg, eg) ((int)((unsigned int)(eg) << 16) + (mg))
#define ScoreMG(s) ((int16_t)((uint16_t)((unsigned)((s)))))
#define ScoreEG(s) ((int16_t)((uint16_t)((unsigned)((s) + 0x8000) >> 16)))
As far as I can tell from my testing, these two versions behave the same, when compared between a c++ and a c program. The main difference is I have replace the final step of mg.s or eg.s (getting the signed part of the union), with a simple cast to int16_t.
Any thoughts, or direction to part of any C standard (using C98, but any version is likely the same here) would be appreciated.