Is there a way to serialize a GMP rational number in binary form? I only see functions for reading/writing to a FILE
, but even there it is a text form. I could convert to numerator/denominator and use the integer functions, but again there only a FILE
output is available. I need to be able to get the raw bytes or write to a C++ stream.
Using the mpz_export
and mpz_import
function (thanks to Marc for pointing that out), I came up with the below code. This is part of a number
class that contains a mpz_class
value.
This really shows that GMP doesn't have a proper import/export functionality. The below is more of a workaround than use of a feature.
void number::write( std::ostream & out ) const {
int8_t neg = value.get_num() < 0;
out.write( (char*)&neg, sizeof(neg) );
size_t c;
void * raw = mpz_export( nullptr, &c, 1, 1, 0, 0, value.get_num().get_mpz_t() );
out.write( (char*)&c, sizeof(c) );
out.write( (char*)raw, c );
free(raw);
raw = mpz_export( nullptr, &c, 1, 1, 0, 0, value.get_den().get_mpz_t() );
out.write( (char*)&c, sizeof(c) );
out.write( (char*)raw, c );
free(raw);
}
void number::read( std::istream & in ) {
mpz_class num, den;
size_t s;
std::vector<uint8_t> v;
int8_t neg;
in.read( (char*)&neg, sizeof(neg) );
in.read( (char*)&s, sizeof(s) );
v.resize(s);
in.read( (char*)&v[0], s );
mpz_import( num.get_mpz_t(), s, 1, 1, 0, 0, &v[0] );
in.read( (char*)&s, sizeof(s) );
v.resize(s);
in.read( (char*)&v[0], s );
mpz_import( den.get_mpz_t(), s, 1, 1, 0, 0, &v[0] );
value = mpq_class(num) / mpq_class(den);
if( neg ) {
value = -value;
}
}