|
Boost Users : |
Subject: Re: [Boost-users] boost::multiprecision::cpp_int encoding and decoding little endian byte arrays
From: John Maddock (john_at_[hidden])
Date: 2013-09-05 04:22:24
> I need to decode/encode cpp_int values from/into byte arrays.
> The encoding must be shortest little endian two's complement
> representation of the value.
> For example:
>
> 00 = 0
> 01 = 1
> ff = -1
> ff:7f = 32767
> 01:80 = -32767
> 00:80:00 = 32768
> 00:80 = -32768
> 01:80:00 = 32769
> ff:7f:ff = -32769
> ff:ff:ef:9c:d2:40:43:da:4f:40:6b:06:6a:cd:92:c2:93:bf:a4:5c:c3:f1:29:63:1d
> = 184467440737095516151844674407370955161518446744073709551615
> 01:00:10:63:2d:bf:bc:25:b0:bf:94:f9:95:32:6d:3d:6c:40:5b:a3:3c:0e:d6:9c:e2
> = -184467440737095516151844674407370955161518446744073709551615
>
> I found a way to archive my goal (see below), but it seems way to complex
> and too inefficient.
> For encoding I basically converting the cpp_int to a uint8_t to get 8 bit
> and then shift the cpp_int by 8, creating a new cpp_int... Twice (once to
> compute it's length, again to encode it).
> For decoding I already shift the byte read to the "right" position and
> "|=" it into the existing cpp_int.
>
> Isn't there an easier way access the binary representation of an cpp_int?
If you don't mind using undocumented internal functions you can access the
underlying array of limbs via:
my_int.backend().limbs()
which returns a pointer to an array of unsigned integers of length
my_int.backend().size(). Note that the type of unsigned integer used varies
by platform, and also by the template arguments passed to cpp_int_backend -
but if you handle the result via a template function that should take care
of that?
HTH, John.
> #include <iostream>
> #include <boost/multiprecision/cpp_int.hpp>
>
> using namespace std;
> using namespace boost::multiprecision;
>
>
> size_t binLength( cpp_int value )
> {
> if ( value.is_zero() )
> return 1;
> if ( value.sign() < 0 )
> value = ~ value;
> size_t length = 0;
> uint8_t lastByte;
> do {
> lastByte = value.convert_to<uint8_t>();
> value >>= 8;
> length ++;
> } while ( ! value.is_zero() );
> if ( lastByte >= 0x80 )
> length ++;
> return length;
> }
>
>
> void binEncode( cpp_int value, uint8_t* output, size_t length )
> {
> if ( value.is_zero() )
> *output = 0;
> else if ( value.sign() > 0 )
> while ( length -- > 0 ) {
> *( output ++ ) = value.convert_to<uint8_t>();
> value >>= 8;
> }
> else {
> value = ~ value;
> while ( length -- > 0 ) {
> *( output ++ ) = ~ value.convert_to<uint8_t>();
> value >>= 8;
> }
> }
> }
>
> cpp_int binDecode( uint8_t* input, size_t length )
> {
> boost::multiprecision::cpp_int result( 0 );
> int bits = - 8;
> while ( length -- > 1 )
> result |= (boost::multiprecision::cpp_int) *( input ++ ) << ( bits += 8 );
> uint8_t a = *( input ++ );
> result |= (boost::multiprecision::cpp_int) a << ( bits += 8 );
> if ( a >= 0x80 )
> result |= (boost::multiprecision::cpp_int) - 1 << ( bits + 8 );
> return result;
> }
>
>
> void test( string s )
> {
> cpp_int x( s );
> uint8_t buffer[ 100 ];
> size_t length = binLength( x ), index = 0;
> binEncode( x, buffer, length );
> cpp_int y = binDecode( buffer, length );
> cout << hex << setw( 2 ) << setfill( '0' ) << (int) buffer[ 0 ];
> while ( -- length > 0 )
> cout << ':' << setw( 2 ) << setfill( '0' ) << (int) buffer[ ++ index ];
> cout << " = " << dec << setw( 1 ) << x << endl;
> if ( x != y )
> cerr << "failed" << endl;
> }
>
>
> int main( int argc, const char* argv[] )
> {
> test( "0" );
> test( "1" );
> test( "-1" );
> test( "32767" );
> test( "-32767" );
> test( "32768" );
> test( "-32768" );
> test( "32769" );
> test( "-32769" );
> test( "184467440737095516151844674407370955161518446744073709551615" );
> test( "-184467440737095516151844674407370955161518446744073709551615" );
> }
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net