#include "bee2/core/mem.h"
#include "bee2/core/u32.h"
#include "bee2/core/util.h"
u32 u32Rev(u32 w)
{
return w << 24 | (w & 0xFF00) << 8 | (w >> 8 & 0xFF00) | w >> 24;
}
void u32Rev2(u32 buf[], size_t count)
{
ASSERT(memIsValid(buf, count * 4));
while (count--)
buf[count] = u32Rev(buf[count]);
}
u32 u32Bitrev(register u32 w)
{
w = ((w >> 1) & 0x55555555) | ((w & 0x55555555) << 1);
w = ((w >> 2) & 0x33333333) | ((w & 0x33333333) << 2);
w = ((w >> 4) & 0x0F0F0F0F) | ((w & 0x0F0F0F0F) << 4);
w = ((w >> 8) & 0x00FF00FF) | ((w & 0x00FF00FF) << 8);
w = (w >> 16) | (w << 16);
return w;
}
size_t u32Weight(register u32 w)
{
w -= ((w >> 1) & 0x55555555);
w = (w & 0x33333333) + ((w >> 2) & 0x33333333);
w = (w + (w >> 4)) & 0x0F0F0F0F;
w += w >> 8;
w += w >> 16;
return (size_t)(w & 0x0000003F);
}
bool_t u32Parity(register u32 w)
{
w ^= w >> 1;
w ^= w >> 2;
w ^= w >> 4;
w ^= w >> 8;
w ^= w >> 16;
return (bool_t)(w & U32_1);
}
size_t SAFE(u32CTZ)(register u32 w)
{
return 32 - u32Weight(w | (U32_0 - w));
}
size_t FAST(u32CTZ)(register u32 w)
{
register u32 t;
size_t l = 32;
if (t = w << 16)
l -= 16, w = t;
if (t = w << 8)
l -= 8, w = t;
if (t = w << 4)
l -= 4, w = t;
if (t = w << 2)
l -= 2, w = t;
CLEAN(t);
return ((u32)(w << 1)) ? l - 2 : l - (w ? 1 : 0);
}
size_t SAFE(u32CLZ)(register u32 w)
{
w = w | w >> 1;
w = w | w >> 2;
w = w | w >> 4;
w = w | w >> 8;
w = w | w >> 16;
return u32Weight(~w);
}
size_t FAST(u32CLZ)(register u32 w)
{
register u32 t;
size_t l = 32;
if (t = w >> 16)
l -= 16, w = t;
if (t = w >> 8)
l -= 8, w = t;
if (t = w >> 4)
l -= 4, w = t;
if (t = w >> 2)
l -= 2, w = t;
CLEAN(t);
return (w >> 1) ? l - 2 : l - (w ? 1 : 0);
}
u32 u32Shuffle(register u32 w)
{
register u32 t;
t = (w ^ (w >> 8)) & 0x0000FF00, w ^= t ^ (t << 8);
t = (w ^ (w >> 4)) & 0x00F000F0, w ^= t ^ (t << 4);
t = (w ^ (w >> 2)) & 0x0C0C0C0C, w ^= t ^ (t << 2);
t = (w ^ (w >> 1)) & 0x22222222, w ^= t ^ (t << 1);
CLEAN(t);
return w;
}
u32 u32Deshuffle(register u32 w)
{
register u32 t;
t = (w ^ (w >> 1)) & 0x22222222, w ^= t ^ (t << 1);
t = (w ^ (w >> 2)) & 0x0C0C0C0C, w ^= t ^ (t << 2);
t = (w ^ (w >> 4)) & 0x00F000F0, w ^= t ^ (t << 4);
t = (w ^ (w >> 8)) & 0x0000FF00, w ^= t ^ (t << 8);
CLEAN(t);
return w;
}
u32 u32NegInv(register u32 w)
{
register u32 ret = w;
ASSERT(w & 1);
ret = ret * (w * ret + 2);
ret = ret * (w * ret + 2);
ret = ret * (w * ret + 2);
ret = ret * (w * ret + 2);
ret = ret * (w * ret + 2);
CLEAN(w);
return ret;
}
void u32From(u32 dest[], const void* src, size_t count)
{
ASSERT(memIsValid(src, count));
ASSERT(memIsValid(dest, ((count + 3) / 4) * 4));
memMove(dest, src, count);
if (count % 4)
memSetZero((octet*)dest + count, 4 - count % 4);
#if (OCTET_ORDER == BIG_ENDIAN)
for (count = (count + 3) / 4; count--;)
dest[count] = u32Rev(dest[count]);
#endif }
void u32To(void* dest, size_t count, const u32 src[])
{
ASSERT(memIsValid(src, (count + 3) / 4 * 4));
ASSERT(memIsValid(dest, count));
memMove(dest, src, count);
#if (OCTET_ORDER == BIG_ENDIAN)
if (count % 4)
{
size_t t = count / 4;
register u32 u = src[t];
for (t *= 4; t < count; ++t, u >>= 8)
((octet*)dest)[t] = (octet)u;
CLEAN(u);
}
for (count /= 4; count--;)
((u32*)dest)[count] = u32Rev(((u32*)dest)[count]);
#endif }