There is a function to set a mpz number with a zero-terminated string.
int mpz_set_str (mpz_t rop, const char *str, int base);
But there is no functions for a non-zero terminated string, and I would like to do that avoiding allocations and changes on the string.
int mpz_set_strn (mpz_t rop, const char *str, size_t n, int base);
I found a similar discussion about this on gmp-discuss
In my case, I would like to use part of the string. I've tried to simulate what the mpz_set_str function does in the background, but it seems it didn't work.
#include <gmp.h>
int main(){
const char * str_base16 = "354a546fde";
mpz_t bn;
mp_size_t xsize;
mpz_init(bn);
// setting bn with part of str_base16
mpz_realloc2(bn, 8*4);
xsize = mpn_set_str(bn->_mp_d, (unsigned char *)str_base16, 8, 16);
bn->_mp_size = xsize;
gmp_printf("%ZX\n", bn);
return 0;
}
Output:
337637766
Looking at the source code for mpz_set_str()
, it looks like you can use the low-level function mpn_set_str()
directly, which takes a pointer and length to digits which start at 0 (not the ASCII character '0'
).
#include <math.h>
#include "gmp.h"
// Convert the string of decimal digits dig[0..n-1], each in the range 0..9, to
// the integer z. (n >= 1)
void dtoz(mpz_t z, unsigned char const *dig, mp_size_t n) {
while (n > 1 && *dig == 0)
dig++, n--;
mp_size_t s = (M_LN10 / M_LN2 / (8 * sizeof(mp_limb_t))) * n + 2;
_mpz_realloc(z, s);
z->_mp_size = mpn_set_str(z->_mp_d, dig, n, 10);
}
int main(void) {
mpz_t z;
mpz_init(z);
unsigned char dig[] = {
3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4,
3, 3, 8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7,
5, 1, 0, 5, 8};
dtoz(z, dig, sizeof(dig));
gmp_printf("%Zd\n", z);
dtoz(z, dig + 12, 12);
gmp_printf("%Zd\n", z);
return 0;
}