Пишу функцию для умножения многочленов в конечном поле по учебнику. Вот код умножения в столбик на си, на вход подаются два многочлена из расширения двоичного поля и многочлен, по которому построено расширение.
Код:
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);
Умножаем
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
на
![$a$ $a$](https://dxdy-01.korotkov.co.uk/f/4/4/b/44bc9d542a92714cac84e01cbbb7fd6182.png)
в столбик. Не
![$a$ $a$](https://dxdy-01.korotkov.co.uk/f/4/4/b/44bc9d542a92714cac84e01cbbb7fd6182.png)
на
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
, это принципиально для понимания кода дальше. Если первый бит
![$a$ $a$](https://dxdy-01.korotkov.co.uk/f/4/4/b/44bc9d542a92714cac84e01cbbb7fd6182.png)
единица, то как при умножении в стобик, прибавляем
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
к результату
Код:
while (a != 0) {
if (a & 1)
result ^= b;
Сдвигаем
![$a$ $a$](https://dxdy-01.korotkov.co.uk/f/4/4/b/44bc9d542a92714cac84e01cbbb7fd6182.png)
, чтобы посмотреть значение следующего бита.
Код:
a >>= 1;
С этого момента непонятно. Для чего сдвигаем
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
, какая математическая логика здесь закодирована?
Код:
b <<= 1;
Если степень
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
больше степени модуля, устраняем переполнение. Но почему вычитаем модуль именно из
![$b$ $b$](https://dxdy-01.korotkov.co.uk/f/4/b/d/4bdc8d9bcfb35e1c9bfb51fc69687dfc82.png)
? Логичнее было бы вычитать его из
![$result$ $result$](https://dxdy-03.korotkov.co.uk/f/6/9/9/69914638c5b78aa32701c82d9b246b1a82.png)
, потому что переполнение может произойти в результате всех сложений и получиться многочлен слишком большой степени, который надо привести по модулю. Или я неправильно понимаю?
Код:
if (degree(b) == d)
b ^= mod;