/** Copyright (C) powturbo 2013-2016 GPL v2 License This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - homepage : https://sites.google.com/site/powturbo/ - github : https://github.com/powturbo - twitter : https://twitter.com/powturbo - email : powturbo [_AT_] gmail [_DOT_] com **/ // vint.c - "Integer Compression" variable byte #ifndef USIZE #include #include #include "conf.h" #include "vint.h" #include "bitutil.h" #define UN 8 // 4 // #define VDELTA 0 #define VBDENC vbdenc #define VBDDEC vbddec #define VBDGETX vbdgetx #define VBDGETGEQ vbdgetgeq #define USIZE 32 #include "vint.c" #undef USIZE #define USIZE 64 #include "vint.c" #undef USIZE #define USIZE 16 #include "vint.c" #undef USIZE #define VDELTA 1 #define VBDENC vbd1enc #define VBDDEC vbd1dec #define VBDGETX vbd1getx #define VBDGETGEQ vbd1getgeq #define USIZE 32 #include "vint.c" #undef USIZE #define USIZE 64 #include "vint.c" #undef USIZE #define USIZE 16 #include "vint.c" #undef USIZE #else #define uint_t TEMPLATE3(uint, USIZE, _t) #if VDELTA == 0 #define OVERFLOWD(in,n,out,vbmax) if(*in == vbmax) { memcpy(out, in+1, n*(USIZE/8)); return in+1+n*(USIZE/8); } #define OVERFLOWE(in,n,out,op,vbmax) if(op > out + n*(USIZE/8)) { *out = vbmax; memcpy(out+1, in, n*(USIZE/8)); op = out+1+n*(USIZE/8); } unsigned char *TEMPLATE2(vbdec, USIZE)(unsigned char *__restrict in, unsigned n, uint_t *__restrict out) { register uint_t x, *op; OVERFLOWD(in, n, out, VB_MAX); #define VBE(_i_) TEMPLATE2(_vbget, USIZE)(in, x, op[_i_] = x) for(op = out; op != out+(n&~(UN-1)); op += UN) { VBE(0); VBE(1); VBE(2); VBE(3); #if UN > 4 VBE(4); VBE(5); VBE(6); VBE(7); #endif __builtin_prefetch(in+16*USIZE, 0); } while(op != out+n) TEMPLATE2(_vbget, USIZE)(in, x, *op++ = x ); return in; } #undef VBE unsigned char *TEMPLATE2(vbenc, USIZE)(uint_t *__restrict in, unsigned n, unsigned char *__restrict out) { uint_t x, *ip; unsigned char *op = out; #define VBD(_i_) x = ip[_i_]; TEMPLATE2(_vbput, USIZE)(op, x, ;); for(ip = in; ip != in+(n&~(UN-1)); ip += UN) { __builtin_prefetch(ip+USIZE*8, 0); VBD(0); VBD(1); VBD(2); VBD(3); #if UN > 4 VBD(4); VBD(5); VBD(6); VBD(7); #endif } while(ip != in+n) { x = *ip++; TEMPLATE2(_vbput, USIZE)(op, x, ;); } OVERFLOWE(in,n,out,op,VB_MAX); return op; } #undef VBD uint_t TEMPLATE2(vbgetx, USIZE)(unsigned char *__restrict in, unsigned idx) { unsigned char *ip; unsigned i; uint_t x; if(*in == 255) return TEMPLATE2(ctou, USIZE)(in+1+idx*(USIZE/8)); for(ip = in,i = 0; i <= idx; i++) ip += TEMPLATE2(_vbvlen, USIZE)(*ip); TEMPLATE2(_vbget, USIZE)(in, x, ;); return x; } /*unsigned TEMPLATE2(vbgeteq, USIZE)(unsigned char *__restrict in, unsigned n, uint_t key, unsigned char **__restrict _ip) { unsigned i; unsigned char *ip; uint_t x; if(*in == 255) { for(ip = (*_ip==in)?in:*ip; ip < in+n; ip+USIZE/8) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); if((x = TEMPLATE2(ctou, USIZE)(ip)) == key) break; } } else for(ip = *_ip,i=idx; i < n; i++) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); if(x == key) break; } *_ip = ip; return i; }*/ unsigned char *TEMPLATE2(vbzenc, USIZE)(uint_t *__restrict in, unsigned n, unsigned char *__restrict out, uint_t start) { uint_t *ip,v; unsigned char *op = out; #define VBZE { v = TEMPLATE2(zigzagenc, USIZE)((*ip)-start); start=*ip++; TEMPLATE2(_vbput, USIZE)(op, v, ;); } for(ip = in; ip != in+(n&~(4-1)); ) { VBZE;VBZE;VBZE;VBZE; } while(ip < in+n) VBZE; //OVERFLOWE(in,n,out,op); return op; } #undef VBZE unsigned char *TEMPLATE2(vbzdec, USIZE)(unsigned char *__restrict in, unsigned n, uint_t *__restrict out, uint_t start) { uint_t x,*op; #define VBZD { TEMPLATE2(_vbget, USIZE)(in, x, ;); *op++ = (start += TEMPLATE2(zigzagdec, USIZE)(x)); } for(op = out; op != out+(n&~(UN-1)); ) { VBZD; VBZD; VBZD; VBZD; #if UN > 4 VBZD; VBZD; VBZD; VBZD; #endif } while(op != out+n) VBZD; return in; } #undef VBZD uint_t TEMPLATE2(vbzgetx, USIZE)(unsigned char *__restrict in, unsigned idx, uint_t start) { unsigned char *ip; unsigned i; uint_t x; for(ip = in,i = 0; i <= idx; i++) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); start += x+1; } return start; } unsigned TEMPLATE2(vbzgeteq, USIZE)(unsigned char **__restrict in, unsigned n, unsigned idx, uint_t key, uint_t start ) { unsigned i; unsigned char *ip; uint_t x; for(ip = *in,i=idx; i < n; i++) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); if((start += x+1) == key) break; } *in = ip; return i; } #endif unsigned char *TEMPLATE2(VBDENC, USIZE)(uint_t *__restrict in, unsigned n, unsigned char *__restrict out, uint_t start) { unsigned char *op = out; if(!n) return out; uint_t *ip, b=0,v; #define VBDE { v = (*ip)-start-VDELTA; start = *ip++; TEMPLATE2(_vbput, USIZE)(op, v, ;); b |= (v /*^ x*/); } for(ip = in; ip != in + (n&~(UN-1)); ) { VBDE;VBDE;VBDE;VBDE; #if UN > 4 VBDE; VBDE; VBDE; VBDE; #endif } while(ip != in+n) VBDE; if(!b) { op = out; *op++ = VB_MAX; } // if (x) { op = out; *op++ = VB_MAX-2; TEMPLATE2(_vbput, USIZE)(op, x, ;); } #if USIZE < 64 OVERFLOWE(in,n,out,op,VB_MAX-1); #endif return op; } #undef VBDE unsigned char *TEMPLATE2(VBDDEC, USIZE)(unsigned char *__restrict in, unsigned n, uint_t *__restrict out, uint_t start) { uint_t x,*op; if(!n) return in; #if USIZE < 64 OVERFLOWD(in,n,out,VB_MAX-1); #endif if(in[0] == VB_MAX) { in++; #if defined(__SSE2__) && USIZE == 32 #if VDELTA == 0 if(n) BITZERO32(out, n, start); #else if(n) BITDIZERO32(out, n, start, VDELTA); #endif #else #if VDELTA == 0 for(x = 0; x < n; x++) out[x] = start; #else for(x = 0; x < n; x++) out[x] = start+x+VDELTA; #endif #endif return in; } #if 0 //USIZE < 64 else if(in[0] == VB_MAX-2) { in++; uint_t z; TEMPLATE2(_vbget, USIZE)(in, z, ;); #if VDELTA == 0 for(x = 0; x < n; x++) out[x] = start+z; #else for(x = 0; x < n; x++) out[x] = start+x+z; #endif return in; } #endif #define VBDD(i) { TEMPLATE2(_vbget, USIZE)(in, x, x+=VDELTA); op[i] = (start += x); } for(op = out; op != out+(n&~(UN-1)); op+=UN) { VBDD(0); VBDD(1); VBDD(2); VBDD(3); #if UN > 4 VBDD(4); VBDD(5); VBDD(6); VBDD(7); #endif } while(op != out+n) VBDD(0); return in; } #undef VBDD uint_t TEMPLATE2(VBDGETX, USIZE)(unsigned char *__restrict in, unsigned idx, uint_t start) { unsigned char *ip; unsigned i; uint_t x; #if USIZE > 64 unsigned long long u; _vbget64(in, u, ;); x = u>>1; start += x+1; if(u & 1) return start + ; #endif for(ip = in; i <= idx; i++) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); start += x+1; } return start; } unsigned TEMPLATE2(VBDGETGEQ, USIZE)(unsigned char **__restrict in, unsigned n, unsigned idx, uint_t *key, uint_t start ) { unsigned i=0; unsigned char *ip=*in; uint_t x; #if USIZE < 64 if(!idx) { unsigned long long u; _vbget64(ip, u, ;); x = u>>1; start += x+1; if((u & 1) && start == *key) { *in = ip; return 0; } i++; } #endif for(ip = *in; i < n; i++) { TEMPLATE2(_vbget, USIZE)(ip, x, ;); if((start += x+VDELTA) == *key) break; } *in = ip; return i; } #undef uint_t #endif