Я пытаюсь реализовать алгоритм умножения Шонхаге-Штрассена, используя NTT, и столкнулся с проблемой, когда конечный результирующий вектор фактически не равен тому, что должен быть.
Для двух входных векторов a
и b
, каждая из которых состоит из N
"цифр" K
битов (конечных N/2
записей каждого набора в 0), каждая, при заданном модуле M = 2^(2*K)+1
, корне единицы w = N^(4*K-1) | w^N = 1 mod M
, модульная инверсия этого значения wi | wi*w = 1 mod M
, и u | u*N = 1 mod M
, следующий код Python используется для (попытки) умножения этих векторов с использованием алгоритма Шонхаге-Штрассена:
#a and b are lists of length N, representing large integers
A = [ sum([ (a[i]*pow(w,i*j,M))%M for i in range(N)]) for j in range(N)] #NTT of a
B = [ sum([ (b[i]*pow(w,i*j,M))%M for i in range(N)]) for j in range(N)] #NTT of b
C = [ (A[i]*B[i])%M for i in range(N)] #A * B multiplied pointwise
c = [ sum([ (C[i]*pow(wi,i*j,M))%M for i in range(N)]) for j in range(N)] #intermediate step in INTT of C
ci = [ (i*u)%M for i in c] #INTT of C, should be product of a and b
В теории,если взять NTT из a
и b
, умножить по точкам, затем взять INTT результата, то я получу произведение, если я не ошибаюсь, и я проверил эти методы для NTT и INTT, чтобы подтвердить, что они являются обратнымидруг с другом. Однако конечный результирующий вектор ci
, а не равен произведению a
и b
, является произведением, в котором каждый элемент берется по модулю M
, что дает неверный результат для произведения.
Например, выполнение теста с N=K=8
и случайными векторами для a, b
дает следующее:
M = 2^(2*8)+1 = 65537
w = 16, wi = 61441
u = 57345
a = [212, 251, 84, 186, 0, 0, 0, 0] (3126131668 as an integer)
b = [180, 27, 234, 225, 0, 0, 0, 0] (3790216116)
NTT(a) = [733, 66681, 147842, 92262, 130933, 107825, 114562, 127302]
NTT(b) = [666, 64598, 80332, 54468, 131236, 186644, 181708, 88232]
Pointwise product of above two lines mod M = [29419, 39913, 25015, 14993, 42695, 49488, 52438, 51319]
INTT of above line (i.e. result) = [38160, 50904, 5968, 11108, 15616, 62424, 41850, 0] (11848430946168040720)
Actual product of a x b = [38160, 50904, 71505, 142182, 81153, 62424, 41850, 0] (11848714628791561488)
В этом примере, и почти каждый раз, когда я его пробую,элементы фактического произведения и результат моего алгоритма одинаковы для нескольких элементов около начала и конца вектора, но к середине они отклоняются. Как я упоминал выше, элементы ci
каждый равен элементам a*b
по модулю M
. Я, должно быть, неправильно понимаю что-то об этом алгоритме, хотя я не совсем уверен, что. Я где-то использую неправильный модуль?