Как можно реализовать умножение в конечных полях?
Если F:= GF(p^n) - конечное поле с p ^ n элементами, где p - простое число, а не натуральное число, существует ли эффективный алгоритм для вычисления произведения двух элементов в F?
Вот мои мысли до сих пор:
Я знаю, что стандартная конструкция F состоит в том, чтобы взять неприводимый многочлен f степени n в GF(p), а затем рассматривать элементы F как многочлены в частном GF(p)[X]/(f), и у меня есть Я чувствую, что это, вероятно, уже правильный подход, поскольку полиномиальное умножение и сложение должно быть легко осуществимо, но я почему-то не понимаю, как это можно сделать на самом деле. Например, как выбрать подходящий f и как получить класс эквивалентности произвольного полинома?
5 ответов
Сначала выберите неприводимый многочлен степени n над GF[p]. Просто порождайте случайные, случайный многочлен неприводим с вероятностью ~ 1 / n.
Чтобы проверить ваши случайные полиномы, вам понадобится некоторый код для разложения полиномов по GF[p], см. Страницу википедии с некоторыми алгоритмами.
Тогда ваши элементы в GF[p^n] являются просто полиномами n-степени над GF[p]. Просто сделайте обычную полиномиальную арифметику и убедитесь, что вычислите остаток по модулю вашего неприводимого полинома.
Кодировать простые версии этой схемы довольно просто. Вы можете сколь угодно усложнить реализацию, скажем, операции по модулю. Смотрите модульное возведение в степень, умножение Монтгомери и умножение с использованием БПФ.
Существует ли эффективный алгоритм умножения элементов в GF(p^n), зависит от того, как вы представляете элементы GF(p^n).
Как вы говорите, один способ действительно работает в GF(p)(X)/(f). Сложение и умножение здесь относительно просты. Однако определить подходящий неприводимый многочлен f непросто - насколько я знаю, не существует эффективного алгоритма для вычисления подходящего f.
Другой способ - использовать так называемые логарифмы Зека. Магма использует их предварительно рассчитанные таблицы для работы с небольшими конечными полями. Возможно, что GAP делает то же самое, хотя его документация менее ясна.
Вычисление с математическими структурами часто довольно сложно. Вы, конечно, не пропустите ничего очевидного здесь.
Это зависит от ваших потребностей и от вашей области.
Когда вы умножаете, вы должны выбрать генератор Fx. Когда вы добавляете, вы должны использовать тот факт, что F является векторным пространством для некоторого меньшего Fpm. На практике то, что вы делаете много времени, - это смешанный подход. Например, если вы работаете над F256, возьмите генератор X из F256x, и пусть G будет минимальным полиномом над F16. Теперь у вас есть
(суммаi меньше 16 ai Xi) (суммаj меньше 16 bj Xj) = сумма sum_ki + j = k ai bj Xi + j
Все, что вам нужно сделать, чтобы сделать умножение эффективным, это сохранить таблицу умножения F16 и (используя G) построить X^m в терминах меньших степеней X и элементов в F16
В итоге, в редком случае, когда pn = 22n, вы получаете поле nimbers Конвея (см. "Пути победы" Конвея или раздел 7.1.3 тома 4А Кнута), для которого существуют очень эффективные алгоритмы.
Полевая арифметическая библиотека Галуа (C++, мод 2, не похоже, что она поддерживает другие простые элементы)
LinBox (C++)
MPFQ (C++)
Однако у меня нет личного опыта (я сделал свои собственные примитивные классы C++ для полей Галуа степени 31 или меньше, ничего слишком экзотического или заслуживающего копирования). Как и один из упомянутых комментаторов, вы можете проверить https://mathoverflow.net/ - просто спросите и убедитесь, что вы сделали свою домашнюю работу в первую очередь. Кто-то должен знать, какие виды математического программного обеспечения подходят для манипулирования конечными полями, и это достаточно близко к области интересов Mathoverflow, поэтому хорошо поставленный вопрос не должен закрываться.
Предположим, что это вопрос для алгоритма, выполняющего умножение в конечных полях, когда идентифицирован монический неприводимый многочлен f(X) (иначе рассмотрите тест Рабина на неприводимость )
У вас есть два многочлена степени n-1
A(X) = a_0 + a_1*X + a_2*X^2 + ... + a_(n-1)*X^(n-1) and
B(X) = b_0 + b_1*X + b_2*X^2 + ... + b_(n-1)*X^(n-1)
Коэффициенты a_k, b_k находятся вне представителей {0,1,..., р-1} из Z / пз .
Продукт определяется как
C(X) = A(X)*B(X) % f(X),
где оператор по модулю «%» - это остаток от полиномиального деления A (X) * B (X) / f(X) .
Ниже приводится подход со сложностью O (n ^ 2).
1.) По закону распределения продукт можно разложить на
B(X) * X_(n-1) * a_(n-1)
+ B(X) * X_(n-2) * a_(n-2)
+ ...
+ B(X) * a_0
знак равно
(...(a_(n-1) * B(X) * X
+ a_(n-2) * B(X)) * X
+ a_(n-3) * B(X)) * X
...
+ a_1 * B(X)) * X
+ a_0 * B(X)
2.) Поскольку% -оператор является гомоморфизмом колец из Z / pZ [X] на GF (p ^ n), он может применяться на каждом шаге итерации выше.
A(X)*B(X) % f(X) =
(...(a_(n-1) * B(X) * X % f(X)
+ a_(n-2) * B(X)) * X % f(X)
+ a_(n-3) * B(X)) * X % f(X)
...
+ a_1 * B(X)) * X % f(X)
+ a_0 * B(X)
3.) После каждого умножения на X , то есть сдвига в пространстве коэффициентов, у вас есть многочлен T_k (X) степени n с элементом t_kn * X ^ n . Приведение по модулю f(X) осуществляется с помощью
T_k(X) % f(X) = T_k(X) - t_kn*f(X),
который является многочленом степени n-1.
Наконец, с редукционным полиномом
r(x) := f(x) - X^n and
T_k(X) =: t_kn * X^n + U_(n-1)(X)
T_k(X) % f(X) = t_kn * X^n + U_(n-1)(X) - t_kn*( r(x) + X^n)
= U_(n-1)(X) - t_kn*r(x)
т.е. все шаги могут быть выполнены с многочленами максимальной степени n-1.