#include "streamvbyte.h" #include "streamvbyte_zigzag.h" #include "streamvbytedelta.h" #include #include #include #include static bool isLittleEndian() { int x = 1; char *c = (char *)&x; return (*c == 1); } // return -1 in case of failure int zigzagtests() { size_t N = 4096; int32_t *datain = malloc(N * sizeof(int32_t)); for(size_t i = 0; i < N; i++) datain[i] = rand() - rand(); uint32_t *dataout = malloc(N * sizeof(uint32_t)); int32_t *databack = malloc(N * sizeof(int32_t)); uint32_t *deltadataout = malloc(N * sizeof(uint32_t)); int32_t *deltadataback = malloc(N * sizeof(int32_t)); zigzag_encode(datain, dataout, N); zigzag_decode(dataout, databack, N); zigzag_delta_encode(datain, deltadataout, N, 0); zigzag_delta_decode(deltadataout, deltadataback, N, 0); int isok = 1; for(size_t i = 0; i < N; i++) { if(datain[i] != databack[i]) { printf("bug\n"); isok = -1; } if(datain[i] != deltadataback[i]) { printf("bug\n"); isok = -1; } } free(databack); free(dataout); free(datain); return isok; } // return -1 in case of failure int basictests() { int N = 4096; uint32_t *datain = malloc(N * sizeof(uint32_t)); // on purpose we mess with the alignment of compressedbufferorig uint8_t *compressedbufferorig = malloc(streamvbyte_max_compressedbytes(N) + sizeof(uint32_t)); uint8_t *compressedbuffer = compressedbufferorig + (sizeof(uint32_t) - 1); uint32_t *recovdata = malloc(N * sizeof(uint32_t)); for (int length = 0; length <= N;) { for (uint32_t gap = 1; gap <= 387420489; gap *= 3) { for (int k = 0; k < length; ++k) datain[k] = gap - 1 + (rand() % 8); // sometimes start with zero // Default encoding: 1,2,3,4 bytes per value size_t compsize = streamvbyte_encode(datain, length, compressedbuffer); size_t usedbytes = streamvbyte_decode(compressedbuffer, recovdata, length); if (compsize != usedbytes) { printf("[streamvbyte_decode] code is buggy length=%d gap=%d: compsize=%d != " "usedbytes=%d \n", (int)length, (int)gap, (int)compsize, (int)usedbytes); return -1; } for (int k = 0; k < length; ++k) { if (recovdata[k] != datain[k]) { printf("[streamvbyte_decode] code is buggy gap=%d\n", (int)gap); return -1; } } // Alternative encoding: 0,1,2,4 bytes per value compsize = streamvbyte_encode_0124(datain, length, compressedbuffer); usedbytes = streamvbyte_decode_0124(compressedbuffer, recovdata, length); if (compsize != usedbytes) { printf("[streamvbyte_decode_0124] code is buggy length=%d gap=%d: compsize=%d != " "usedbytes=%d \n", (int)length, (int)gap, (int)compsize, (int)usedbytes); return -1; } for (int k = 0; k < length; ++k) { if (recovdata[k] != datain[k]) { printf("[streamvbyte_decode_0124] code is buggy gap=%d\n", (int)gap); return -1; } } } // Delta-encoded functions for (size_t gap = 1; gap <= 531441; gap *= 3) { for (int k = 0; k < length; ++k) datain[k] = gap * k; size_t compsize = streamvbyte_delta_encode(datain, length, compressedbuffer, 0); size_t usedbytes = streamvbyte_delta_decode(compressedbuffer, recovdata, length, 0); if (compsize != usedbytes) { printf("[streamvbyte_delta_decode] code is buggy gap=%d, size " "mismatch %d %d \n", (int)gap, (int)compsize, (int)usedbytes); return -1; } for (int k = 0; k < length; ++k) { if (recovdata[k] != datain[k]) { printf("[streamvbyte_delta_decode] code is buggy gap=%d\n", (int)gap); return -1; } } } if (length < 128) ++length; else { length *= 2; } } free(datain); free(compressedbufferorig); free(recovdata); return 0; } // return -1 in case of failure int aqrittests() { uint8_t in[16]; uint8_t compressedbuffer[32]; uint8_t recovdata[16]; memset(compressedbuffer, 0, 32); memset(recovdata, 0, 16); for (int i = 0; i < 0x10000; i++) { in[0] = (uint8_t)((i >> 0) & 1); in[1] = (uint8_t)((i >> 1) & 1); in[2] = (uint8_t)((i >> 2) & 1); in[3] = (uint8_t)((i >> 3) & 1); in[4] = (uint8_t)((i >> 4) & 1); in[5] = (uint8_t)((i >> 5) & 1); in[6] = (uint8_t)((i >> 6) & 1); in[7] = (uint8_t)((i >> 7) & 1); in[8] = (uint8_t)((i >> 8) & 1); in[9] = (uint8_t)((i >> 9) & 1); in[10] = (uint8_t)((i >> 10) & 1); in[11] = (uint8_t)((i >> 11) & 1); in[12] = (uint8_t)((i >> 12) & 1); in[13] = (uint8_t)((i >> 13) & 1); in[14] = (uint8_t)((i >> 14) & 1); in[15] = (uint8_t)((i >> 15) & 1); const int length = 4; size_t compsize = streamvbyte_encode((uint32_t *)in, length, compressedbuffer); size_t usedbytes = streamvbyte_decode(compressedbuffer, (uint32_t *)recovdata, length); if (compsize != usedbytes) { printf("[streamvbyte_decode] code is buggy"); return -1; } for (size_t k = 0; k < length * sizeof(uint32_t); ++k) { if (recovdata[k] != in[k]) { printf("[streamvbyte_decode] code is buggy"); return -1; } } compsize = streamvbyte_encode_0124((uint32_t *)in, length, compressedbuffer); usedbytes = streamvbyte_decode_0124(compressedbuffer, (uint32_t *)recovdata, length); if (compsize != usedbytes) { printf("[streamvbyte_decode_0124] code is buggy"); return -1; } for (size_t k = 0; k < length * sizeof(uint32_t); ++k) { if (recovdata[k] != in[k]) { printf("[streamvbyte_decode_0124] code is buggy"); return -1; } } } return 0; } int main() { if(zigzagtests() == -1) return -1; if (basictests() == -1) return -1; if (aqrittests() == -1) return -1; printf("Code looks good.\n"); if (isLittleEndian()) { printf("And you have a little endian architecture.\n"); } else { printf("And you have a big endian architecture.\n"); printf("Warning: produced compressed bytes may not be interoperable with " "little endian systems.\n"); } #ifdef __AVX__ printf("Code was vectorized (x64).\n"); #elif defined(__ARM_NEON__) printf("Code was vectorized (ARM NEON).\n"); #else printf("Warning: you tested non-vectorized code.\n"); #endif return 0; }