Como o @DavidRicherby já aponta, a confusão surge porque diferentes medidas de complexidade estão se misturando. Mas deixe-me elaborar um pouco.
Geralmente, ao estudar algoritmos para multiplicação polinomial por anéis arbitrários, interessa-se o número de operações aritméticas no anel que um algoritmo usa. Em particular, dado alguns anéis (comutativos, unitários) e dois polinômios de grau menor que , o algoritmo Schönhage-Strassen precisa de multiplicações e adições em para calcular , aproximando-se da ésima raiz primitiva da unidade de para para obter um anel maior e, em seguida, usando o Fast Transformada de Fourier sobreRf,g∈R[X]nO(nlognloglogn)Rfg∈R[X]nRD⊃RD, Calculando o produto em .D
Se o anel contém um raiz -ésimo de unidade, então este pode ser acelerado para operações em , usando a Fast Fourier Transform directamente sobre . Mais especificamente, em , você pode fazer isso usando operações de anel (ignorando o fato de que isso exigiria aritmética exata sobre os números complexos).nO(nlogn)RRZ⊂CO(nlogn)
A outra medida que pode ser levada em consideração é a complexidade de bits de uma operação. E é nisso que estamos interessados ao multiplicar dois números inteiros de comprimento de bit . Aqui, as operações primitivas estão se multiplicando e adicionando dois dígitos (com carry). Portanto, ao multiplicar dois polinômios sobre , é necessário levar em consideração o fato de que os números que surgem durante o cálculo não podem ser multiplicados usando um número constante de operações primitivas. Isso e o fato de que não possui a ésima raiz primitiva da unidade para impede que você aplique o algoritmo . Você supera isso considerandonZZnn>2O(nlogn)f,gcom coeficientes do anel , pois os coeficientes do polinômio do produto não excederão esse limite. Lá (quando é uma potência de dois), você tem (a classe de congruência de) como a ésima raiz da unidade e, chamando recursivamente o algoritmo para multiplicações de coeficientes, você pode obter um total de ) operações primitivas (isto é, bit). Isso então é transferido para a multiplicação inteira.Z/⟨2n+1⟩n2nO(nlognloglogn)
Para um exemplo que destaca bem a importância da diferença entre operações em anel e operações primitivas, considere dois métodos para avaliar polinômios: o método de Horner e o método de Estrin. O método de Horner avalia um polinômio em algum explorando a identidade
enquanto de Estrin método divide em duas partes
e
ie, contém os termos de grau e os termos de grauf=∑ni=0fiXix∈Z
f(x)=(…(fnx+fn−1)x+…+…)+f0
fH=∑i=1n/2fn/2+iXi
L=∑i=0n/2fiXi
H>n/2L≤n/2(suponha que é uma potência de dois, por simplicidade).
n
Então, podemos calcular usando
e aplicando o algoritmo recursivamente.f(x)
f(x)=H(x)xn/2+L(x)
O primeiro, usando adições e multiplicações, provou ser ótimo em relação ao número de adições e multiplicações (isto é, operações em anel), o último precisa de mais (pelo menos ).nn+logn
Mas, no nível das operações de bits, pode-se (facilmente) mostrar que, no pior dos casos, o método de Horner realiza multiplicações de números de tamanho pelo menos , levando a muitos bits operações (isso ocorre mesmo se assumirmos que dois números de bits podem ser multiplicados no tempo ), enquanto o esquema de Estrin usa operações para algumas operações , que é, de longe, assintoticamente mais rápido.n/2n/2Ω(n2)nO(n)O(nlogcn)=O~(n)c>0