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

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

#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 ответ

Решение

Из 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 - передача по ссылке).

Другие вопросы по тегам