Schönhage–Strassen 정수 곱셈 알고리즘을 구현하려고했지만 재귀 단계에서 걸림돌을 쳤습니다.
이 I 값이 와 비트 및 I를 계산하려는 X ^ 2 \ pmod를 2 ^ {n은 + 1} . 나는 원래 아이디어가 선택하는 줄 알았는데 K 있도록 4 ^ K \ GEQ 2N , 분할 X 로 K ^ 2 각 조각 2 ^ {K-1} 비트 모듈로 작업하는 동안, SSA의 회선을 적용 2 ^ {2 ^ 케이} +1 , 값당 2 ^ k 비트의 용량을 가진 링 . 그러나 컨벌루션의 출력은 2n 비트 보다 약간 더 큽니다 (즉, > 2 ^ k각 출력 값이 여러 제품의 합이므로 링당 용량보다 큰 출력 값당 비트 수) 작동하지 않습니다. 2 패딩의 추가 요소를 추가해야했습니다.
패딩에서 2의 추가 요소는 복잡성을 망칩니다. 재귀 단계가 너무 비쌉니다. 대신에게 알고리즘, I는 결국 와 알고리즘.
Wikipedia에서 링크 된 몇 가지 참고 자료를 읽었지만이 문제가 어떻게 해결되는지에 대한 세부 사항을 살펴 보았습니다. 예를 들어, 2 의 거듭 제곱이 아닌 p에 대해 modulo 2 ^ {p 2 ^ k} + 1 을 사용 하여 여분의 패딩 오버 헤드를 피할 수 있습니다 ...하지만 전원이 아닌 경우 남은 2 개의 요인으로, 개수를 두 배로 늘리지 않으면 Cooley-Tukey를 적용 할 수 없습니다. 또한 p 는 곱하기 역 모듈로 2 ^ p + 1을 갖지 않을 수 있습니다 . 따라서 2 가지 요소가 여전히 도입되고 있습니다.
점근 적 복잡성을 불식시키지 않고 재귀 단계에서 사용할 링을 어떻게 선택합니까?
또는 의사 코드 형식으로 :
multiply_in_ring(a, b, n):
...
// vvv vvv //
// vvv HOW DOES THIS PART WORK? vvv //
// vvv vvv //
let inner_ring = convolution_ring_for_values_of_size(n);
// ^^^ ^^^ //
// ^^^ HOW DOES THIS PART WORK? ^^^ //
// ^^^ ^^^ //
let input_bits_per_piece = ceil(n / inner_ring.order);
let piecesA = a.splitIntoNPiecesOfSize(inner_ring.order, input_bits_per_piece);
let piecesB = b.splitIntoNPiecesOfSize(inner_ring.order, input_bits_per_piece);
let piecesC = inner_ring.negacyclic_convolution(piecesA, piecesB);
...