2
votes

For example, I would like to do something like this:

#include <gmp.h>
typedef mpz_t Integer;

// 
Integer F(Integer a,Integer b,Integer c,Integer d) {
    Integer ret = times(plus(a,b),plus(c,d));
}

But, GMP doesn't let me do this, apparently mpz_t is an array, so I get the error:

error: ‘F’ declared as function returning an array

So instead I would have to do something like this:

void F(Integer ret,Integer a,Integer b,Integer c,Integer d) {
    Integer tmp1,tmp2;

    plus(tmp1,a,b);     
    plus(tmp2,c,d);     
    times(ret,tmp1,tmp2); 
}

This is unnatural, and not following the logical way that C (or in general mathematical) expressions can be composed. In fact, you can't compose anything in a math-like way because apparently you can't return GMP numbers! If I wanted to write - for example - a simple yacc/bison style parser that converted a simple syntax using +, -, /, * etc. into C code implementing the given expressions using GMP it seems it would be much more difficult as I would have to keep track of all the intermediate values.

So, how can I force GMP to bend to my will here and accept a more reasonable syntax? Can I safely "cheat" and cast mpz_t to a void * and then reconstitute it at the other end back into mpz_t? I'm assuming from reading the documentation that it is not really passing around an array, but merely a reference, so why can't it return a reference as well? Is there some good sound programming basis for doing it this way that I should consider in writing my own program?

1
typedef Integer mpz_t; Did you compile this? – Pascal Cuoq
whoops, no, I didn't copy/paste from my source I just manually re-typed and apparently swapped those two around. I have corrected that mistake, thanks! – Michael

1 Answers

3
votes

From gmp.h:

typedef __mpz_struct mpz_t[1];

This makes a lot of sense, and is pretty natural. Think about it: having an array of size 1 allows you to deal with an obscured pointer (known as opaque reference) and all its advantages:

mpz_t number;
DoubleIt(number); /* DoubleIt() operates on `number' (modifies it) as
                     it will be passed as a pointer to the real data */

Were it not an array, you'd have to do something like:

mpz_t number;
DoubleIt(&number);

And then it comes all the confusion. The intention behind the opaque type is to hide these, so you don't have to worry about it. And one of the main concerns should be clear: size (which leads to performance). Of course you can't return such struct that holds data limited to the available memory. What about this one (consider mpz_t here as a "first-class" type):

mpz_t number = ...;
number = DoubleIt(number);

You (the program) would have to copy all the data in number and push it as a parameter to your function. Then it needs to leave appropriate space for returning another number even bigger.

Conclusion: as you have to deal with data indirectly (with pointers) it's better to use an opaque type. You'll be passing a reference only to your functions, but you can operate on them as if the whole concept was pass-by-reference (C defaults to pass-by-reference).