Cannot 'new' a GMP object

R

Richard Cavell

#include <gmp.h>

mpz_t* p_mympz = new mpz_t;

error: cannot convert '__mpz_struct*' to '__mpz_struct (*)[1]' in
initialization

1. What does that mean?

2. Given that mpz_t doesn't have a constant sizeof() I take it that
dynamic creation (new/delete) is the only way I can create an array of
them (that is, keep their pointers in an array and use the -> operator).
 
R

Rolf Magnus

Richard said:
#include <gmp.h>

mpz_t* p_mympz = new mpz_t;

error: cannot convert '__mpz_struct*' to '__mpz_struct (*)[1]' in
initialization

1. What does that mean?

Seems that mpz_t is a typedef for an array. If you allocate an array with
new, you get a pointer to the first element, not a pointer to the array.
Anyway, I wonder why there would be a typedef for an array with exactly one
element.
2. Given that mpz_t doesn't have a constant sizeof()

What do you mean? sizeof() is resolved at compile time. It _always_ returns
a compile-time constant.
I take it that dynamic creation (new/delete) is the only way I can create
an array of them (that is, keep their pointers in an array and use the ->
operator).

Well, if the number of elements is not know until it is created, yes.
However, you can use std::vector instead, which handles the memory
management details for you.
 
R

Richard Cavell

Seems that mpz_t is a typedef for an array. If you allocate an array with
new, you get a pointer to the first element, not a pointer to the array.
Anyway, I wonder why there would be a typedef for an array with exactly one
element.

typedef __mpz_struct mpz_t[1];

__mpz_struct is typedef'ed to a struct which has 2 ints and one pointer.
The GMP code is too advanced for me but I'm guessing that mpz_t[1] is
intended to point to the end of the structure rather than the start.
What do you mean? sizeof() is resolved at compile time. It _always_ returns
a compile-time constant.

I'm making the point, though, that if I could know that sizeof() were
constant I could create vector<mpz_t> instead of vector<mpz_t*>
 
C

Chris Croughton

Seems that mpz_t is a typedef for an array. If you allocate an array with
new, you get a pointer to the first element, not a pointer to the array.
Anyway, I wonder why there would be a typedef for an array with exactly one
element.

typedef __mpz_struct mpz_t[1];

__mpz_struct is typedef'ed to a struct which has 2 ints and one pointer.
The GMP code is too advanced for me but I'm guessing that mpz_t[1] is
intended to point to the end of the structure rather than the start.

It's declared that way so that a C program can pass it as a sort of
reference parameter:

mpz_t a, b, c;
mpz_init2(a, 1);
mpz_init2(b, 2);
mpz_init(c);
mpz_add(c, a, b);

instead of having to put & in front of all of the variables to pass them
as pointers explicitly. Unfortunately this really messes with the types
in C++, and I wouldn't guarantee that vector<> and other containers work
properly (I remember having some problems at one time, but I'm not sure
whether they now work).
I'm making the point, though, that if I could know that sizeof() were
constant I could create vector<mpz_t> instead of vector<mpz_t*>

Try using the C++ wrapper instead (mpz_class). Its major disadvantage
is that it sets up each variable every time it is created, including
temporaries:

mpz_class a, b, c;
a = 1;
b = "2000";
c = a + (a * b);

will allocate a temporary for (a * b) and initialise it, then throw it
away after use, calling malloc() and free(), which takes a lot of time.
If you stick to simple expressions though this won't happen (it has
optimisations so that (x = a + b; and the like are done as a single
operation). For instance, I've done timings on the following:

r = (a*b + c*d) / (a + b*c + d);

r = a*b;
tmp = c*d;
r += tmp;
tmp = b*c;
tmp += a;
tmp += d;
r /= tmp;

and the differences (on Debian GNU/Linux 'woody', Duron 1200 CPU) are a
factor of 3-4 for mpz_class and a factor of 2 for mpf_class (floating
point, both with default precision 128). The second form is comparable
in speed to using the C GMP functions directly.

Chris C
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top