Как преобразовать соглашение о параметрах GMP C в нечто более естественное? - PullRequest
2 голосов
/ 29 марта 2012

Например, я хотел бы сделать что-то вроде этого:

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

Но GMP не позволяет мне сделать это, по-видимому, mpz_t - это массив, поэтому я получаю ошибку:

error: ‘F’ declared as function returning an array

Так что вместо этого я должен был бы сделать что-то вроде этого:

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

Это неестественно и не следует логическому способу составления C (или вообще математических) выражений. На самом деле, вы не можете ничего составить математически, потому что, очевидно, вы не можете вернуть номера GMP! Если бы я хотел написать, например, простой синтаксический анализатор стиля yacc / bison, который преобразовал простой синтаксис с использованием +, -, /, * и т. Д. В код C, реализующий данные выражения с использованием GMP, то, кажется, это было бы намного сложнее, поскольку я придется отслеживать все промежуточные значения.

Итак, как я могу заставить GMP подчиниться моей воле и принять более разумный синтаксис? Могу ли я безопасно "обмануть" и привести mpz_t к пустоте *, а затем восстановить его на другом конце обратно в mpz_t? Читая документацию, я предполагаю, что это не на самом деле , проходящий вокруг массива, а просто ссылка, так почему же он не может также вернуть ссылку? Есть ли какая-то хорошая основа звукового программирования для такой работы, которую я должен рассмотреть при написании своей собственной программы?

1 Ответ

3 голосов
/ 29 марта 2012

С gmp.h :

typedef __mpz_struct mpz_t[1];

В этом много смысла, а вполне естественно . Подумайте об этом: имея массив размером 1 позволяет вам иметь дело с скрытым указателем (известным как непрозрачный справка) и все его преимущества:

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

Если бы это не массив, вам бы пришлось сделать что-то вроде:

mpz_t number;
DoubleIt(&number);

А потом приходит все смятение. Целью непрозрачного типа является чтобы скрыть это, так что вам не нужно беспокоиться об этом. И один из главных Проблемы должны быть ясны: размер (что приводит к производительности). Конечно ты не может вернуть такую ​​структуру, которая содержит данные, ограниченные доступной памятью. Какие об этом (рассмотрим mpz_t здесь как «первоклассный» тип):

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

Вы (программа) должны были бы скопировать все данные в number и выдать их как параметр вашей функции. Тогда ему нужно оставить соответствующее место для возвращая еще один номер еще больше.

Вывод: поскольку вы должны иметь дело с данными косвенно (с указателями), это Лучше использовать непрозрачный тип. Вы будете передавать ссылку только на ваш функции, но вы можете работать с ними, как будто вся концепция передача по ссылке (по умолчанию C передача по ссылке ).

...