Пишу функцию для умножения многочленов в конечном поле по учебнику. Вот код умножения в столбик на си, на вход подаются два многочлена из расширения двоичного поля и многочлен, по которому построено расширение.
Код:
gf_element multiply(gf_element a, gf_element b, gf_element mod) {
gf_element result = 0;
a = rem(a, mod);
b = rem(b, mod);
int d = degree(mod);
while (a != 0) {
if (a & 1)
result ^= b;
a >>= 1;
b <<= 1;
if (degree(b) == d)
b ^= mod;
}
return result;
}
Здесь
Цитата:
using gf_element = unsigned int;
Как работает этот алгоритм? Я понимаю только половину:
Приводим многочлены по модулю, если их степень больше, чем степень модуля
Код:
a = rem(a, mod);
b = rem(b, mod);
Умножаем
на
в столбик. Не
на
, это принципиально для понимания кода дальше. Если первый бит
единица, то как при умножении в стобик, прибавляем
к результату
Код:
while (a != 0) {
if (a & 1)
result ^= b;
Сдвигаем
, чтобы посмотреть значение следующего бита.
Код:
a >>= 1;
С этого момента непонятно. Для чего сдвигаем
, какая математическая логика здесь закодирована?
Код:
b <<= 1;
Если степень
больше степени модуля, устраняем переполнение. Но почему вычитаем модуль именно из
? Логичнее было бы вычитать его из
, потому что переполнение может произойти в результате всех сложений и получиться многочлен слишком большой степени, который надо привести по модулю. Или я неправильно понимаю?
Код:
if (degree(b) == d)
b ^= mod;