Question about creating and displaying mpf
Markus Törnqvist
mjt at nysv.org
Tue Sep 14 15:59:57 CEST 2010
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?
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
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
More information about the gmp-discuss
mailing list