#include "streamvbyte.h"
#if defined(_MSC_VER)
#include <intrin.h>
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
#include <x86intrin.h>
#elif defined(__GNUC__) && defined(__ARM_NEON__)
#include <arm_neon.h>
#elif defined(__GNUC__) && defined(__IWMMXT__)
#include <mmintrin.h>
#elif (defined(__GNUC__) || defined(__xlC__)) && \
(defined(__VEC__) || defined(__ALTIVEC__))
#include <altivec.h>
#elif defined(__GNUC__) && defined(__SPE__)
#include <spe.h>
#endif
#include <string.h>
#include "streamvbyte_shuffle_tables_decode.h"
#ifdef __ARM_NEON__
#include "streamvbyte_arm_decode.c"
#endif
#ifdef STREAMVBYTE_SSSE3
#include "streamvbyte_x64_decode.c"
#endif
static inline uint32_t _decode_data(const uint8_t **dataPtrPtr, uint8_t code) {
const uint8_t *dataPtr = *dataPtrPtr;
uint32_t val;
if (code == 0) { val = (uint32_t)*dataPtr;
dataPtr += 1;
} else if (code == 1) { val = 0;
memcpy(&val, dataPtr, 2); dataPtr += 2;
} else if (code == 2) { val = 0;
memcpy(&val, dataPtr, 3); dataPtr += 3;
} else { memcpy(&val, dataPtr, 4);
dataPtr += 4;
}
*dataPtrPtr = dataPtr;
return val;
}
static const uint8_t *svb_decode_scalar(uint32_t *outPtr, const uint8_t *keyPtr,
const uint8_t *dataPtr,
uint32_t count) {
if (count == 0)
return dataPtr;
uint8_t shift = 0;
uint32_t key = *keyPtr++;
for (uint32_t c = 0; c < count; c++) {
if (shift == 8) {
shift = 0;
key = *keyPtr++;
}
uint32_t val = _decode_data(&dataPtr, (key >> shift) & 0x3);
*outPtr++ = val;
shift += 2;
}
return dataPtr; }
size_t __slow5_streamvbyte_decode(const uint8_t *in, uint32_t *out, uint32_t count) {
if (count == 0)
return 0;
const uint8_t *keyPtr = in; uint32_t keyLen = ((count + 3) / 4); const uint8_t *dataPtr = keyPtr + keyLen;
#ifdef STREAMVBYTE_SSSE3
dataPtr = svb_decode_avx_simple(out, keyPtr, dataPtr, count);
out += count & ~ 31;
keyPtr += (count/4) & ~ 7;
count &= 31;
#elif defined(__ARM_NEON__)
dataPtr = svb_decode_vector(out, keyPtr, dataPtr, count);
out += count - (count & 3);
keyPtr += count/4;
count &= 3;
#endif
return svb_decode_scalar(out, keyPtr, dataPtr, count) - in;
}