Question about creating and displaying mpf

Case Vanhorsen casevh at gmail.com
Tue Sep 14 16:56:40 CEST 2010


[ gmpy is maintained independently from GMP so this discussion should
probably continue off this list. ]

2010/9/14 Markus Törnqvist <mjt at nysv.org>:
> Hi!
>
> I just found GMP and its Python bindings as a good replacement for the
> dead-slow Python Decimal data type.
>
> However, being new to extending Python, I have annoying memory leaks that
> can't be found with Valgrind, as it doesn't understand Python's memory
> manager.
>
> Therefore I came up with the idea of using the C structures directly,
> which might be a bit faster than going through the Python boilerplate,
> but that didn't turn out painlessly either.
>
> In Python I re-use the old Decimal interface, so I create gmpy.mpf
> objects like D('1.678')
>
> When I print it out in C code, from the Python object, its printed as
> mpf('1.67800000000000000002e0')
>
> * Question one is: Why is that not the given value? Did it store
> it badly, like a regular badly-rounded float, or is that representation only?
>

It is stored as a binary floating point number.

> I'm not entirely clear on the innards of gmpy, but it seems it uses
> its own PympfObject types for data storage.
>
> The way I found to access the original data is the Pympf_AS_MPF macro, which
> is (((PympfObject *)(foo))->f) and is used in gmpy code.
>
> For me, however, it doesn't work.
>
>  gmp_printf("%f\n", (((PympfObject *)(foo))->f)); // prints out 0.000000

I haven't tried this, but shouldn't that be "%F\n" ?
>
> foo is a regular PyObject *, but PympfObject stores the mpf_t in ->f so
> that should, I guess, just work, but doesn't.
>
> Using gdb (and the appropriate Python macros) I can get something meaningful
> out like
>
>  (gdb) print Pympf_ascii(foo, 10, 0, -2, 8, 0)
>  $2 = (PyObject *) 0x10770f0
>  (gdb) pyo $2
>  object  : '1.66599999999999999999'
>  type    : str
>  refcount: 1
>  address : 0x10770f0
>
> but that only works on Python objects. But it kinda goes to prove that
> the value is somehow accessible :)
>
> * So question number two is: what am I missing here? Why can't I use
> the Pympf_AS_MPF macro to gmp_printf() the real value?
>
> I try to set it into new variables, like
>
>  mpf_t tmp;
>
>  mpf_init(tmp);
>  mpf_set(tmp, Pympf_AS_MPF(foo));
>
> And gmp_printf(...) tells me 0.000000
>
> No matter how I try to set this, it fails
>
>  mpf_t tmp;
>
>  mpf_init(tmp);
>  mpf_set_str(tmp, PyString_AsString(PyObject_Str(foo)), 10);
>
> Same thing(!)
>
> Also
>
>  mpf_t tmp;
>
>  mpf_init(tmp);
>  mpf_set_ui(tmp, 42);
>
> Does not work; it's all about zeroes.
>
> This is so strange, those are vastly different things, every one, but
> all fail the same way.
>
> What *does* semi-work is getting the string the hard way
> from the MPF:
>
>  char *mpf_in_buffer;
>  char *mpf_out_buffer;
>  mp_exp_t the_exp;
>
>  int base = 10;
>  int digits = 0;
>
>  int tmp_retval = 0;
>
>  mpf_in_buffer = mpf_get_str(0, &the_exp, base, digits, Pympf_AS_MPF(foo));
>  printf("\tmpf_in_buffer: %s\n", mpf_in_buffer);
>
>  sprintf(mpf_out_buffer, "%s@%d", mpf_in_buffer, (int) the_exp);
>  printf("\tmpf_out_buffer: %s\n", mpf_out_buffer);
>
>  tmp_retval = mpf_set_str(tmp, mpf_out_buffer, base);
>  gmp_printf("\ttmp (%d) %f\n", tmp_retval, tmp);
>
> Results in the output
>
>  mpf_in_buffer: 167800000000000000002
>  mpf_out_buffer: 167800000000000000002 at 1
>  tmp (0) 0.000000
>
> I do assume that @ is the correct separator between mantissa and exponent,
> as the documentation says "if the base is 10 or less" and tmp_retval == 0.
>
> Clearly the Pympf_AS_MPF macro can't be all bad because it magickally
> works for mpf_get_str(). But why?
>
> * What am I doing wrong?
>
> There is the saying "select() is not broken", but I've been
> studying the GMP manual harder than anything and now
> just breaking apart here; it would be nice of the bug was
> actually in Debian's libgmp3-dev (2:4.3.2+dfsg-1)
>
> PS.
> Are there any convenient GDB macros for GMP?
> I tried writing my own to print all relevant data for
> an MPF:
>
> define mpf
>  set $ob = $arg0
>  printf "size: %d\n", $ob->_mp_size
>  printf "prec: %d\n", $ob->_mp_prec
>  printf "limbs:\n"
>  set $i = 0
>  while (++$i <= $ob->_mp_size)
>    printf "\t%d\n", $ob->_mp_d[$i]
>  end
> end
>
> but realised how hard it actually is to represent
> the limbs, the hard way with mpf_get_str, and as I clearly
> can't call gmp_printf() or anything else usefully,
> I guess I'm screwed, right?
>
> Thanks for any help!
>
> --
> mjt
>
> _______________________________________________
> gmp-discuss mailing list
> gmp-discuss at gmplib.org
> https://gmplib.org/mailman/listinfo/gmp-discuss
>

casevh


More information about the gmp-discuss mailing list