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