Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unpacked failed for some value (like 0x90000000) #5

Open
arc0035 opened this issue May 24, 2018 · 0 comments
Open

unpacked failed for some value (like 0x90000000) #5

arc0035 opened this issue May 24, 2018 · 0 comments

Comments

@arc0035
Copy link

arc0035 commented May 24, 2018

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:

  1. move the sign bit to rightmost and revert the data payload . The progress:
    10010000000000000000000000000000->00100000000000000000000000000000->
    1101 1111111 1111111 1111111 1111111
  2. 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:

  1. recover the packed value to the "reverted value". The result is
    11011111111111111111111111111111 which means it works fine. lets give this value a name "v".
  2. 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant