Hi,
In raw.hpp, for signed int 32, it looks like some value will have unpack errors.
For example ,if I pack value "0x90000000"(whose binary code is 10010000000000000000000000000000 and in demical it is -1879048192) using "pack( Stream& s, const unsigned_int& v )", the steps are:
- move the sign bit to rightmost and revert the data payload . The progress:
10010000000000000000000000000000->00100000000000000000000000000000->
1101 1111111 1111111 1111111 1111111
- pack the value for every 7 bits with a flag indicating whether there is more 1s. T the packed value is:
0000000000000000000000000000110111111111111111111111111111111111
The packed part works fine. But when I unpack the value it gets another value instead of 0x90000000.
I use the algorithm in "unpack( Stream& s, signed_int& vi ) ". The steps are:
- recover the packed value to the "reverted value". The result is
11011111111111111111111111111111 which means it works fine. lets give this value a name "v".
- recover the original value from v. Three steps are taken:
a). value= ((v>>1) ^ (v>>31)) + (v&0x01); whose value is 1879048191 (01101111111111111111111111111111).
b). value = v&0x01 ? value : -value; which yields 1879048191
c). value = -value which yields -1879048191
so, after the unpack function, the value is -1879048191 instead of -1879048192.
Here is the code I used to test. I'm using a uint64_t to hold packed bytes instead of Stream in raw.hpp:
#include <iostream>
#include <bitset>
using namespace std;
uint64_t pack(int32_t value){
uint32_t val = (value<<1) ^ (value>>31);
int k=0;
uint64_t packed = 0 ;
do {
cout << "round" << endl;
uint8_t b = uint8_t(val) & 0x7f;
val >>= 7;
b |= ((val > 0) << 7);
packed |= (uint64_t)b << k;
k += 8;
} while( val );
return packed;
}
int32_t unpackSigned(uint64_t packed){
uint32_t v = 0; char b = 0; int by = 0;
do {
b = packed & 0xff;
v |= uint32_t(uint8_t(b) & 0x7f) << by;
by += 7;
packed >>= 8;
} while( uint8_t(b) & 0x80 );
int value = 0;
value = ((v>>1) ^ (v>>31)) + (v&0x01);
value = v&0x01 ? value : -value;
value = -value;
return value;
}
int main() {
int32_t v = 0x90000000;
uint64_t packed = pack(v);
int32_t r =unpackSigned(packed);
cout << v << endl;
cout << r << endl;
}
In my test this unpack written by me works:
int32_t unpackSigned(uint64_t packed){
uint32_t v = 0; char b = 0; int by = 0;
do {
b = packed & 0xff;
v |= uint32_t(uint8_t(b) & 0x7f) << by;
by += 7;
packed >>= 8;
} while( uint8_t(b) & 0x80 );
int value = 0;
/*
value = ((v>>1) ^ (v>>31)) + (v&0x01);
cout << (v>>31) << endl;
value = v&0x01 ? value : -value;
value = -value;
*/
if(v&0x01 == 1){
v ^= 0xffffffff;
v >>= 1;
value = 0x80000000 + v;
}
else{
value = v >>= 1;
}
return value;
}
Could you please help to research this?@bytemaster