¿Cómo convertir la convención de parámetros GMP C en algo más natural?

Por ejemplo, me gustaría hacer algo como esto:

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

Pero, GMP no me deja hacer esto, aparentemente mpz_t es una matriz, así que me sale el error:

 error: 'F' declared as function returning an array 

Así que en vez tendría que hacer algo como esto:

 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); } 

Esto es antinatural y no sigue la forma lógica en que se pueden componer las expresiones C (o en general, las matemáticas). De hecho, no puede componer nada de forma matemática porque aparentemente no puede devolver números GMP. Si quisiera escribir, por ejemplo, un simple analizador de estilo yacc / bison que convirtiera una syntax simple usando +, -, /, * etc. en el código C implementando las expresiones dadas usando GMP, parece que sería mucho más difícil porque Habría que hacer un seguimiento de todos los valores intermedios.

Entonces, ¿cómo puedo forzar a GMP a que se doble a mi voluntad aquí y acepte una syntax más razonable? ¿Puedo “hacer trampa” de forma segura y lanzar mpz_t a un vacío * y luego reconstituirlo en el otro extremo de nuevo en mpz_t? Supongo que, al leer la documentación, no se trata realmente de una matriz, sino simplemente de una referencia, ¿por qué no puede devolver una referencia también? ¿Hay alguna buena base de progtwigción para hacerlo de esta manera que debería considerar al escribir mi propio progtwig?

Desde gmp.h :

 typedef __mpz_struct mpz_t[1]; 

Esto tiene mucho sentido, y es bastante natural . Piénselo: tener una matriz de tamaño 1 le permite lidiar con un puntero oculto (conocido como referencia opaca) y todas sus ventajas:

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

Si no fuera una matriz, tendrías que hacer algo como:

 mpz_t number; DoubleIt(&number); 

Y luego viene toda la confusión. La intención detrás del tipo opaco es ocultar estos, para que no tenga que preocuparse por ello. Y una de las principales preocupaciones debe ser clara: el tamaño (que conduce al rendimiento). Por supuesto, no puede devolver tal estructura que contiene datos limitados a la memoria disponible. ¿Qué pasa con este (considere mpz_t aquí como un tipo de “primera clase”):

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

Usted (el progtwig) tendría que copiar todos los datos en number y empujarlo como un parámetro a su función. Entonces debe dejar espacio apropiado para devolver otro número aún más grande.

Conclusión: como tiene que tratar los datos indirectamente (con punteros) es mejor usar un tipo opaco. Solo pasará una referencia a sus funciones, pero puede operar en ellas como si todo el concepto fuera paso por referencia (C por defecto es paso por referencia ).