Skip to content

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

@arc0035

Description

@arc0035

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions