[Fwd: Re: Bug affecting mpq_class::get_num() and mpq_class::get_den()?]

Dear Gerardo,
I am forwarding this to the mailing list as I am sure others are interested in this issue.
If I understand correctly, in GMP 4.0.1 and 4.1 there is no way to obtain an mpz_class& (or const mpz_class&) to the numerator or denominator of an mpq_class, right? In other words, is it correct to say that numerator and denominator as mpz_class objects can only be obtained by making copies? All the best
Roberto
-------- Original Message -------- Subject: Re: Bug affecting mpq_class::get_num() and mpq_class::get_den()? Date: Mon, 10 Jun 2002 12:20:24 +0200 From: gerardo.ballabio@unimib.it (Ballabio Gerardo - Dip. di Scienza dei Materiali) To: Kevin Ryde user42@zip.com.au CC: Roberto Bagnara bagnara@cs.unipr.it, Torbjorn Granlund tege@swox.se References: 87k7p9bdqi.fsf@zip.com.au
On 2002.06.09 00:35 Kevin Ryde wrote:
This bug report looks real unfortunately. Is it perhaps due to the difference between "mpz_classref" and "mpz_class&"? mpz_class::get_num seems to work in other simpler contexts.
$ g++ -W -Wall -c gmpbug.cc gmpbug.cc: In function `mpz_class& numerator(mpq_class&)': gmpbug.cc:24: could not convert `__gmp_expr<__gmpq_value, __gmpq_value>::get_num()' to `mpz_class&'
#include <gmpxx.h>
mpz_class& numerator(mpq_class& r) { return r.get_num(); }
Yes, you got the point. "mpz_classref" is not the same as "mpz_class &", and I can't define a conversion from "mpz_classref" to "mpz_class &" because there's _no_ "mpz_class" to be referenced! Indeed, such an "mpz_class" could only be a temporary object, and it wouldn't be correct to take a reference to it -- as soon as the temporary goes out of scope (in your example, as soon as numerator() is exited and the reference is returned!), the reference is broken. (Furthermore, in the current implementation, creating an mpz_class from an mpz_t makes a _copy_ of the original mpz_t, thus we could read but not write to it!)
As far as I can see, the only way out is to add two mpz_classes to the representation of mpq_class, and "symlink" the two underlying mpz_t's to the mpq_t (or remove the mpq_t and rewrite all mpq operations in terms of mpz operations, but I don't think we want to): then we can throw away mpz_classref, and reference the two mpz_classes directly. That would also be a considerable simplification of the implementation; but I don't know very much about the internals of mpz_t and mpq_t, and I'm not sure that such "symlinking" can be done (actually, I looked into gmp.h, but I'm quite confused about mpz_t being defined as "typedef __mpz_struct mpz_t[1];").
Otherwise, I can only suggest to leave the code as it is, and to change the documentation like this:
mpz_classref mpq_class::get_num () mpz_classref mpq_class::get_den ()
Get an `mpz_classref' referencing to the numerator or denominator of an `mpq_class'. This can be used both for read and write access. If the object returned is modified, it modifies the original `mpq_class'.
`mpz_classref' is an internal GMP++ type acting like an `mpz_class &'. You can use it as if it were an `mpz_class', except that you can't take a reference to that (nonexisting) `mpz_class' -- this includes passing it to a function that requires an `mpz_class &' argument.
Do you feel this is too big a limitation?
Gerardo
participants (1)
-
Roberto Bagnara