Линейная библиотека линейных алгебр конечного поля (например, GF (2 ^ 128)/GF (2 ^ 256))

Общие

Я ищу библиотеку, которая умеет делать точные вычисления на больших конечных полях, таких как GF (2 128)/𝔽 2 128 и GF (2 256)/𝔽 2 256. Я перечислил функции, которые мне нужны, и функции, которые были бы прохладными ниже. Очевидно, что библиотека должна быть как можно быстрее:-). Ах, поскольку я не являюсь начальником С++ (и, вероятно, большинство библиотек С++), пример кода, например, генерирует случайный элемент/константу и умножает на него мультипликативный обратный

Обязательные функции

  • Добавление элементов поля
  • Умножение элемента поля
  • Найти мультипликативный обратный элемент поля

Приятно иметь функции

  • Поддержка Vector/Matrix
  • Поддержка случайных элементов.

Библиотеки, на которые я уже смотрел, вероятно, не будут работать

  • FFLAS/FFPACK, похоже, не работает с такими большими конечными полями
  • Givaro, похоже, не работает на таких больших конечных полях

Библиотеки, на которые я уже смотрел, могут работать (но я не мог использовать)

  • NTL, я не смог инвертировать элемент, но он должен действительно работать с SAGE, кажется, использует эту библиотеку при определении GF (2 ^ 256), и там элемент можно инвертировать с помощью x^(-1)
  • PARI/GP, я не смог найти все, что мне нужно в документации, но в документации документации SAGE говорится, что он должен работать

Другие примечания

  • Я пишу программу Haskell и позже буду взаимодействовать с этой библиотекой, так проще интерфейс Haskell лучше: -)

Ответы

Ответ 1

Библиотека NTL, похоже, работает, используя это (извините, что я не могу запрограммировать на С++) код

#include <NTL/GF2E.h>
#include <NTL/GF2EX.h>
#include <NTL/GF2X.h>
#include <NTL/GF2XFactoring.h>

NTL_CLIENT

int main()
{
    GF2X P = BuildIrred_GF2X(256);
    GF2E::init(P);

    GF2E zero = GF2E::zero();
    GF2E one;
    GF2E r = random_GF2E();
    GF2E r2 = random_GF2E();
    conv(one, 1L);
    cout << "Cardinality: " << GF2E::cardinality() << endl;
    cout << "ZERO: " << zero << " --> " << IsZero(zero) << endl;
    cout << "ONE:  " << one  << " --> " << IsOne(one)   << endl;
    cout << "1/r:  " << 1/r  << ", r * (1/r): " << (r * (1/r)) << endl;
    cout << "1/r2:  " << 1/r2  << ", r2 * (1/r2): " << (r2 * (1/r2)) << endl;
}

похоже, работает, доказательство (вывод этой программы):

Cardinality: 115792089237316195423570985008687907853269984665640564039457584007913129639936
ZERO: [] --> 1
ONE:  [1] --> 1
1/r:  [0 1 0 1 1 0 1 1 1 0 1 1 1 0 0 1 1 0 1 1 1 0 1 1 0 0 0 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 0 1 0 0 1 0 1 1 1 0 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 1 0 1 1 1 1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 0 1 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 1], r * (1/r): [1]
1/r2:  [1 0 1 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 0 1 1 0 0 1 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 0 0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 0 1 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 1 0 1 0 0 1 1], r2 * (1/r2): [1]

Кажется, что работает даже инвертирование (прокрутите как можно выше в примере выше): -)