source: thirdparty/SZ/sz/include/pastriGeneral.h @ 2c47b73

Revision 2c47b73, 7.0 KB checked in by Hal Finkel <hfinkel@…>, 6 years ago (diff)

more work on adding SZ (latest version)

  • Property mode set to 100644
Line 
1#ifndef PASTRIGENERAL_H
2#define PASTRIGENERAL_H
3
4
5static inline double abs_FastD(double x){
6  u_UI64I64D u1;
7  u1.d=x;
8  //(*((uint64_t *)(&x)))&=(int64_t)0x7FFFFFFFFFFFFFFF;
9  u1.ui64&=(int64_t)0x7FFFFFFFFFFFFFFF;
10  return u1.d;
11}
12
13static inline int64_t abs_FastI64(int64_t x){
14  return (x^((x&(int64_t)0x8000000000000000)>>63))+((x&(int64_t)0x8000000000000000)!=0);
15}
16/*
17int abs(int x) {
18   int mask = (x >> (sizeof(int) * CHAR_BIT - 1));
19   return (x + mask) ^ mask;
20}
21*/
22
23
24
25
26//Returns the min. bits needed to represent x.
27//Same as: ceil(log2(abs(x)))
28//Actually to be completely safe, it correspond to: ceil(log2(abs(i)+1))+0.1
29//+0.1 was for fixing rounding errors
30//REMEMBER: To represent the whole range [-x:x], the number of bits required is bitsNeeded(x)+1
31static inline int bitsNeeded_double(double x){
32  u_UI64I64D u1;
33  u1.d=x;
34  return (((u1.ui64<<1)>>53)-1022) & (((x!=0)<<31)>>31);
35}
36
37//Returns the min. bits needed to represent x.
38//Same as: ceil(log2(abs(x)))
39//NEEDS OPTIMIZATION!
40static inline int bitsNeeded_float(float x){
41  u_UI64I64D u1;
42  u1.d=x; //Casting to Double!
43  return (((u1.ui64<<1)>>53)-1022) & (((x!=0)<<31)>>31);
44}
45
46static inline int bitsNeeded_UI64(uint64_t x){
47  int shift;
48  int res=0;
49 
50  //Get the absolute value of x:
51  //x=(x^((x&(int64_t)0x8000000000000000)>>63))+((x&(int64_t)0x8000000000000000)!=0);
52  //x=abs_FastI64(x);
53 
54  //printf("%d\n",(x&(uint64_t)0xFFFFFFFF00000000)!=0);
55  shift=(((x&(uint64_t)0xFFFFFFFF00000000)!=0)*32);
56  x>>=shift;
57  res+=shift;
58 
59  //printf("%d\n",(x&(uint64_t)0x00000000FFFF0000)!=0);
60  shift=(((x&(uint64_t)0x00000000FFFF0000)!=0)*16);
61  x>>=shift;
62  res+=shift;
63 
64  //printf("%d\n",(x&(uint64_t)0x000000000000FF00)!=0);
65  shift=(((x&(uint64_t)0x000000000000FF00)!=0)*8);
66  x>>=shift;
67  res+=shift;
68 
69  //printf("%d\n",(x&(uint64_t)0x00000000000000F0)!=0);
70  shift=(((x&(uint64_t)0x00000000000000F0)!=0)*4);
71  x>>=shift;
72  res+=shift;
73 
74  //printf("%d\n",(x&(uint64_t)0x000000000000000C)!=0);
75  shift=(((x&(uint64_t)0x000000000000000C)!=0)*2);
76  x>>=shift;
77  res+=shift;
78 
79  //printf("%d\n",(x&(uint64_t)0x0000000000000002)!=0);
80  shift=((x&(uint64_t)0x0000000000000002)!=0);
81  x>>=shift;
82  res+=shift;
83 
84  //printf("%d\n",(x&(uint64_t)0x0000000000000001)!=0);
85  shift=((x&(uint64_t)0x0000000000000001)!=0);
86  x>>=shift;
87  res+=shift;
88 
89  //printf("BITS NEEDED: %d\n",res);
90  return res;
91}
92
93static inline int bitsNeeded_I64(int64_t x){
94  uint64_t ux;
95  ux=abs_FastI64(x);
96  return bitsNeeded_UI64(ux);
97}
98
99//Implementations(They are inline, so they should be in this header file)
100
101static inline int myEndianType(){ //Should work for most cases. May not work at mixed endian systems.
102  uint64_t n=1;
103  if (*(unsigned char*)&n == 1){
104    //cout<<"Little-Endian"<<endl;
105    return 0;  //0 for little endian
106  }
107  else{
108    //cout<<"Big-Endian"<<endl;
109    return 1; //1 for big endian
110  }
111}
112
113static inline void flipBytes_UI64(uint64_t *dataPtr){
114  unsigned char*tempA;
115  char temp8b;
116  tempA=(unsigned char*)dataPtr;
117  temp8b=tempA[7];
118  tempA[7]=tempA[0];
119  tempA[0]=temp8b;
120  temp8b=tempA[6];
121  tempA[6]=tempA[1];
122  tempA[1]=temp8b;
123  temp8b=tempA[5];
124  tempA[5]=tempA[2];
125  tempA[2]=temp8b;
126  temp8b=tempA[4];
127  tempA[4]=tempA[3];
128  tempA[3]=temp8b;
129  return;
130}
131
132//WARNING: readBits works properly only on Little Endian machines! (For Big Endians, some modifications are needed)
133
134static inline uint64_t readBits_UI64(unsigned char* buffer,uint64_t *bitPosPtr,char numBits){ // numBits must be in range [0:56]
135    uint64_t mask = ((uint64_t)0x0000000000000001<<numBits)-1;
136    //cout<<"bitPos:"<<(*bitPosPtr)<<"\tbitPos>>3:"<<(*bitPosPtr>>3)<<endl;
137    uint64_t temp64b = *(uint64_t*)(buffer + ( *bitPosPtr >> 3)); 
138    //NOTE: bitPos>>3 is the same as bitPos/8
139    temp64b >>= (*bitPosPtr) & (uint64_t)0x0000000000000007;
140   
141    //cout<<endl;
142    //cout<<"bitpos>>3:"<<(bitPos>>3)<<" bitPos&0x7:"<<(bitPos & 0x00000007)<<" bitPos%8:"<<(bitPos%8)<<endl;
143    //cout<<"Read:"<<(temp64b & mask)<<" temp64b:"<<temp64b<<" Mask:"<<mask<<" numBits:"<<numBits<<endl;
144   
145    (*bitPosPtr) += numBits;
146    return (temp64b & mask);
147}
148
149static inline int64_t readBits_I64(unsigned char* buffer,uint64_t *bitPosPtr,char numBits){ // numBits must be in range [0:56]
150  int64_t val;
151  val=readBits_UI64(buffer,bitPosPtr,numBits);//Read value
152  int64_t shiftAmount=64-numBits;
153  val=(val<<shiftAmount)>>shiftAmount;//Sign correction
154  return val;
155}
156
157//WARNING: readBits_EndianSafe is not tested on Big-Endian machines
158static inline uint64_t readBits_EndianSafe(unsigned char* buffer,uint64_t *bitPosPtr,char numBits){ // numBits must be in range [0:56]
159    uint64_t mask = ((uint64_t)0x0000000000000001<<numBits)-1;
160    uint64_t temp64b = *(uint64_t*)(buffer + ((*bitPosPtr)>>3)); 
161    //NOTE: (*bitPosPtr)>>3 is the same as (*bitPosPtr)/8
162    if(myEndianType())
163      flipBytes_UI64(&temp64b);
164    temp64b >>= (*bitPosPtr) & (uint64_t)0x0000000000000007;
165    (*bitPosPtr) += numBits;
166    return temp64b & mask;
167}
168
169//WARNING: writeBits_Fast works properly only on Little Endian machines! (For Big Endians, some modifications are needed)
170//The buffer should be initialized as 0's for this to work!
171//Also, the range of data is not checked!(If data exceeds numBits, it may be cause problems)
172static inline void writeBits_Fast(unsigned char* buffer,uint64_t *bitPosPtr,char numBits,int64_t data){
173    //if(DEBUG){printf("writeBits_Fast: data:0x%lx %ld\n",data,data);} //DEBUG
174    //if(DEBUG){printf("writeBits_Fast: numBits:0x%lx %ld\n",numBits,numBits);} //DEBUG
175    uint64_t mask = ((uint64_t)0x0000000000000001<<numBits)-1;
176    //if(DEBUG){printf("writeBits_Fast: mask:0x%lx %ld\n",mask,mask);} //DEBUG
177    //if(DEBUG){printf("writeBits_Fast: data&mask:0x%lx %ld\n",((*(uint64_t*)&data)&mask),((*(uint64_t*)&data)&mask));} //DEBUG
178   
179    //if(DEBUG){printf("writeBits_Fast: buffer_O:0x%lx\n",*(uint64_t*)(buffer + ((*bitPosPtr)>>3)));} //DEBUG
180    *(uint64_t*)(buffer + ((*bitPosPtr)>>3)) |= ((*(uint64_t*)&data)&mask) << ((*bitPosPtr) & (uint64_t)0x0000000000000007);
181    //if(DEBUG){printf("writeBits_Fast: buffer_N:0x%lx\n",*(uint64_t*)(buffer + ((*bitPosPtr)>>3)));} //DEBUG
182
183   
184    (*bitPosPtr) += numBits;
185}
186
187//WARNING: writeBits_EndianSafe is not tested on Big-Endian machines
188static inline void writeBits_EndianSafe(unsigned char* buffer,uint64_t *bitPosPtr,char numBits,uint64_t data){
189    uint64_t mask = ((uint64_t)0x0000000000000001<<numBits)-1;
190    data=data&mask;
191    uint64_t temp64b_inBuffer=*(uint64_t*)(buffer + ((*bitPosPtr)>>3));
192    uint64_t temp64b_outBuffer=data << ((*bitPosPtr) & (uint64_t)0x0000000000000007);
193    if(myEndianType()){
194      flipBytes_UI64(&temp64b_inBuffer);
195    }
196    temp64b_outBuffer |= temp64b_inBuffer;
197    if(myEndianType()){
198      flipBytes_UI64(&temp64b_outBuffer);
199    }
200    *(uint64_t*)(buffer + ((*bitPosPtr)>>3))=temp64b_outBuffer;  // "|=" may also work
201    (*bitPosPtr) += numBits;
202}
203
204
205#endif
Note: See TracBrowser for help on using the repository browser.