Reputation: 370
I need to convert mpz_class
types to vector<byte>
and the other way around.
I implemented these two functions, but roundtrip conversion is broken.
typedef unsigned char byte;
std::vector<byte> mpz_to_vector(std::shared_ptr<mpz_class> x) {
size_t size;
byte *a = (byte *) mpz_export(NULL, &size, 1, 1, 1, 0,x->get_mpz_t());
std::vector<byte> p(a,a+size);
free(a);
return p;
}
std::shared_ptr<mpz_class>vector_to_mpz(std::vector<byte> d) {
mpz_class ptr;
mpz_import(ptr.get_mpz_t(), d.size(), 1, sizeof(mpz_t), 1, 0, (void *) d.data());
auto tmp = std::shared_ptr<mpz_class>(new mpz_class(ptr));
return tmp;
}
Upvotes: 2
Views: 2371
Reputation: 45654
Avoid dynamic allocations, especially the manual kind: Why is size
a pointer to a dynamically allocated size_t
?
You don't need any temporary buffers, so remove them. The manual contains the proper algorithm for sizing the output buffer.
Applying this, we get this exporter:
std::vector<byte> mpz_to_vector(const mpz_t x) {
size_t size = (mpz_sizeinbase (x, 2) + CHAR_BIT-1) / CHAR_BIT;
std::vector<byte> v(size);
mpz_export(&v[0], &size, 1, 1, 0, 0, x);
v.resize(size);
return v;
}
inline std::vector<byte> mpz_to_vector(std::shared_ptr<mpz_class>& x) {
return mpz_to_vector(x->get_mpz_t());
}
The importer suffers from needless copying too.
Still, the only error is providing wrong arguments to mpz_export
.
Correcting that all gives us:
std::shared_ptr<mpz_class> vector_to_mpz(const std::vector<byte>& d) {
auto p = make_shared<mpz_class>();
mpz_import(p->get_mpz_t(), d.size(), 1, 1, 0, 0, &d[0]);
return p;
}
BTW: I used make_shared
, because that's more efficient on good implementations than doing so manually, and it enables exception safety.
Upvotes: 3