Wie wird der Innenring im Schönhage-Strassen-Algorithmus gewählt?


9

Ich habe versucht, den Ganzzahl-Multiplikationsalgorithmus Schönhage-Strassen zu implementieren, bin aber im rekursiven Schritt auf einen Stolperstein gestoßen.

Ich habe einen Wert mit n Bits und möchte x 2 berechnenxn . Ich dachte ursprünglich, die Idee wäre, ein k sozu wählen,dass 4 k2 n , x in 2 k Stücke mit jeweils 2 k - 1 Bit aufgeteilt wird, die SSA-Faltung anwenden, während modulo 2 2 k + 1 , ein Ring mit 2 k Bit, arbeitet Kapazität pro Wert, dann setzen Sie die Teile wieder zusammen. Die Ausgabe der Faltung hat jedoch etwas mehr als 2 n Bits (dh > 2 kx2(mod2n+1)k4k2nx2k2k122k+12k2n>2kBits pro Ausgabewert, was mehr als die Kapazität des Rings ist, da jeder Ausgabewert eine Summe mehrerer Produkte ist. Dies funktioniert also nicht. Ich musste einen zusätzlichen Faktor von 2 Polsterung hinzufügen.

Dieser zusätzliche Faktor 2 in der Polsterung ruiniert die Komplexität. Das macht meinen rekursiven Schritt zu teuer. Anstelle eines Algorithmus, ich erhalte ein F ( n ) = n lg n + F(n)=nlgn+nF(2n)=Θ(nlgnlglgn)Algorithmus.F(n)=nlgn+nF(4n)=Θ(nlg2n)

Ich habe ein paar Referenzen gelesen, die aus Wikipedia verlinkt sind, aber alle scheinen die Details zu beschönigen, wie dieses Problem gelöst wird. Zum Beispiel könnte ich den zusätzlichen Auffüllaufwand vermeiden, indem ich Modulo für ein p arbeite , das keine Potenz von 2 ist ... aber dann brechen die Dinge erst später ab, wenn ich nur Faktoren habe, die keine Potenz von 2 sind verbleibend und kann Cooley-Tukey nicht anwenden, ohne die Anzahl der Stücke zu verdoppeln. Außerdem darf p kein multiplikatives inverses Modulo 2 p + 1 haben . Es werden also immer noch erzwungene Faktoren von 2 eingeführt.2p2k+1pp2p+1

Wie wähle ich den Ring aus, der während des rekursiven Schritts verwendet werden soll, ohne die asymptotische Komplexität zu beeinträchtigen?

Oder in Pseudocodeform:

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);
  ...

Bitte posten Sie nicht dieselbe Frage auf mehreren Websites . Jede Community sollte einen ehrlichen Versuch haben, zu antworten, ohne dass jemand Zeit verschwendet. Ich schlage vor, Sie löschen eine der beiden Kopien.
DW

@ DW Fertig. Ich habe Cross-Posts veröffentlicht, nachdem cs eine Woche lang keine Antworten gegeben hatte, weil ich dachte, dass es für diese Site zu schwierig ist. Wollte offensichtlich alle Antworten zurück verlinken.
Craig Gidney

Ich verstehe. Wenn es in Zukunft auftaucht, können Sie Ihren Beitrag jederzeit für die Aufmerksamkeit des Moderators markieren und um eine Migration bitten, und wir können ihn für Sie auf CSTheory verschieben. Danke für Ihr Verständnis!
DW

3
2ν2n

IIRC Sie hatten eine teilweise Selbstantwort auf die jetzt gelöschte CS-Frage. Es scheint eine Schande, das zu verlieren. Könnten Sie es hier einfügen (in die Frage, damit die Frage nicht als bereits beantwortet markiert wird)?
Peter Taylor

Antworten:


4

Diese Antwort stammt aus dem Artikel "Asymptotisch schnelle Algorithmen zur numerischen Multiplikation und Division von Polynomen mit komplexen Koeffizienten" , den Markus in den Kommentaren verlinkt hat.


n2n+1

  • psn=(p1)2ssp2s

  • 2mn

    m=s/2+1s2=s/2+1p2=p/2+1

    s2p2s2p22s22m2s2p22n+m+1

  • Führen Sie die FFT-basierte negacyclische Faltung an den Stücken und dem Rest wie gewohnt durch.

pnm2m(p21)2s2s

F(s)()(p1)2sm+2mF(s/2+1)()2s2s(s/2+1)+2s/2+1F(s/2+1)()s22s+22s/2F(s/2+1)()s22s+4(s/2)22s+16(s/4)22s+...()2ss2lg(s)()nlgn(lgnlgn)2lglgnlgn()nlgn(lg2n)lglgn()n(lgn)lglgn

Das scheint ungefähr richtig zu sein, obwohl ich in diesen Schritten ziemlich viel betrogen habe.

s2ssslognps

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.