Алгоритм Тоома — Кука

Алгоритм Тоома — Кука, иногда упоминаемый как Тоом-3 — это алгоритм умножения[англ.] больших чисел, названный именами Андрея Леоновича Тоома[англ.], предложившего новый алгоритм с низкой сложностью, и Стивена Кука, более ясно его описавшего.

Если даны два больших числа a и b, согласно алгоритму Тоома — Кука, нужно разбить a и b на k меньших частей каждое длиной l и осуществить операции над элементами. При росте k можно комбинировать часть операций умножения частей разбиения, сокращая тем самым общую сложность алгоритма. Произведение частей разбиения можно затем вычислить с помощью того же самого алгоритма Тоома — Кука рекурсивно. Термины «алгоритм Тоома-3» и «алгоритм Тоома — Кука» иногда ошибочно используются как синонимы, хотя Тоом-3 является лишь частным случаем алгоритма Тоома — Кука для k = 3.

Тоом-3 сокращает сложность с 9 умножений до 5 и работает за время . В общем случае Тоом-k работает за время , где , является временем, затрачиваемым на умножения подчастей, а c — время, затрачиваемое на сложения и умножение на малые константы [1]. Алгоритм Карацубы является частным случаем алгоритма Тоома — Кука, где число разбивается на две части. Он сокращает сложность с 4 умножений до 3, а потому работает за время . Обычное умножение в столбик эквивалентно Тоом-1 со сложностью .

Хотя степень e может быть установлена как можно близкой к 1 путём увеличения k, функция c растёт очень быстро[1][2]. Скорость роста для смешанных схем Тоома — Кука оставалась открытой проблемой к 2005-му году[3]. Реализация, описанная Дональдом Кнутом, добивается сложности [4].

За счёт накладных расходов алгоритм Тоома-Кука для малых чисел медленнее умножения в столбик и потому обычно использовался для множителей среднего размера, пока не был обнаружен асимптотически более быстрый алгоритм Шёнхаге — Штрассена (со сложностью .

Тоом описал свой алгоритм в 1963 году, а Кук опубликовал улучшенный (асимптотически эквивалентный) алгоритм в тезисах своей диссертации в 1966-м году[5].

Детали

править

В этой секции обсуждается работа алгоритма Тоома-k для любого заданного значения k и даётся упрощённое описание умножения Тоома — Кука многочленов, которое описал Марко Бодрато[6]. Алгоритм имеет пять основных шагов:

  1. Разбиение
  2. Вычисление в точках
  3. Поточечное умножение
  4. Интерполяция
  5. Рекомпозиция

В типичной интерпретации больших чисел каждое целое представляется как последовательность цифр в позиционной системе счисления, где основанием счисления берётся некоторое (обычно большое) значение b. В нашем примере мы используем  , так что каждая цифра соответствует группе из четырёх десятичных цифр (в реализации в компьютере в качестве b обычно берётся степень двойки). Скажем, нужно перемножить два числа:

m = 12 3456 7890 1234 5678 9012
n = 9 8765 4321 9876 5432 1098.

Они много меньше, чем обычно обрабатываются алгоритмом Тоома — Кука, но они здесь иллюстрируют алгоритм.

Разбиение

править

Первым шагом является выбор основания счисления  , так что число цифр как у числа m, так и у числа n по основанию B не превосходит k (например, 3 в Тоом-3). Обычно i задаётся выражением:

 

В нашем примере мы будем использовать Тоом-3, так что мы выбираем  . Теперь мы разбиваем m и n по их основанию счисления B на цифры  :

 

Мы будем использовать эти цифры как коэффициенты в многочленах p и q степени (k − 1), со свойствами   и  :

 
 

После введения этих многочленов получаем, что если мы вычислим произведение  , то ответом задачи будет  .

В случае, когда перемножаемые числа имеют разные размеры, полезно использовать разные значения k для m и n, которые мы будем обозначать   и  . Например, алгоритм «Тоом-2.5» относится к алгоритму Тоома-Кука с   и  . В этом случае i в   обычно выбирается по выражению

 

Вычисление в точках

править

Подход Тоома — Кука вычисления произведения многочленов   обычен. Заметим, что многочлен степени d единственным образом определяется   точками (например, прямая — это многочлен степени 1 и определяется двумя точками). Идеей является вычисление p(•) и q(•) в различных точках. Затем осуществляется произведение значений в этих точках, чтобы получить значения произведения многочленов. Наконец, интерполируем полученные значения для получения коэффициентов многочлена.

Поскольку  , нам нужно   точек для получения конечного результата. Назовём его d. В случае Тоом-3  . Алгоритм будет работать независимо от того, какие точки были выбраны (с несколькими небольшими исключениями — см. требование обратимости матрицы в разделе Интерполяция), но для упрощения алгоритма лучше использовать небольшие значения типа 0, 1, −1 и −2.

Одна необычная точка, которая часто используется, это бесконечность, то есть  . Чтобы «вычислить» многочлен p на бесконечности, берут предел   при стремлении x к бесконечности. Следовательно,   всегда равно значению старшего коэффициента (в примере выше — коэффициента  ).

В нашем примере Тоом-3 мы используем точки 0, 1, −1, −2 и  . Этот выбор упрощает вычисление в точках и даёт формулы:

 

И аналогично для q. В нашем примере, значения, которые мы получаем, равны:

  =   = 56789012 = 56789012
  =   =   = 135813702
  =   =   = −21988766
  =   =   = −100519632
  =   = 123456 = 123456
  =   = 54321098 = 54321098
  =   =   = 97639739
  =   =   = 11199987
  =   =   = −31723594
  =   = 98765 = 98765.

Как видно, эти значения могут быть отрицательными.

Для дальнейших объяснений полезно рассматривать этот процесс вычисления в точках как умножение матрицы на вектор справа, где каждая строка матрицы содержит степени одной из выбранных точек, а вектор содержит коэффициенты многочлена:

 

Размерности матриц равны   для p и   для q. Строка для значения бесконечность имеет нулевые значения за исключением последнего столбца, в котором стоит 1.

Более быстрое вычисление значений

править

Вычисление значений в точках может быть выполнено быстрее, чем указано в приведённых выше формулах. Число элементарных операций (сложение/вычитание) может быть сокращено. Последовательность операций, придуманная Бодрато[6] для Тоом-3, показана здесь для первого операнда (многочлена p):

      = 56789012 + 123456 = 56912468
  =   = 56789012 = 56789012
  =   = 56912468 + 78901234 = 135813702
  =   = 56912468 − 78901234 = −21988766
  =   =   = − 100519632
  =   = 123456 = 123456.

Эта последовательность требует пять операций сложения/вычитания, на единицу меньше, чем при прямом вычислении. Более того, нам не нужно умножать на 4 при вычислении p(−2).

Поточечное умножение

править

В отличие от умножения многочленов p(•) и q(•), умножение вычисленных значений p(a) и q(a) просто сводится к умножению целых — более простого варианта исходной задачи. Мы рекурсивно используем нашу процедуру умножения для вычисления каждой пары значений в точках. В практических реализациях, когда операнды становятся меньше, алгоритм сводится к умножению в столбик[англ.]. Если r — произведение многочленов, в нашем примере мы имеем:

  =   =   = 3084841486175176
  =   =   = 13260814415903778
  =   =   = −246273893346042
 ) =   =   = 3188843994597408
  =   =   = 12193131840.

Как видим, эти значения могут быть отрицательными. Для достаточно больших чисел это наиболее дорогой шаг, единственный шаг, не зависящий линейно от размеров m и n.

Интерполяция

править

Это наиболее сложный шаг, обратный шагу вычисления в точках — если даны наши d точек произведения многочленов r(•), мы должны вычислить его коэффициенты. Другими словами, мы должны решить матричное уравнение с вектором в правой части:

 

Эта матрица строится так же, как и на шаге вычисления значений многочлена в точках, за исключением, что матрица имеет размер d × d. Мы можем решить это уравнение с помощью метода Гаусса (метода исключений), но это будет очень дорого. Вместо этого мы используем факт, что используемые для вычисления значений точки выбраны специальным образом, позволяющим легко вычислить обратную матрицу (см. также Матрица Вандермонда), а тогда:

 

Теперь остаётся лишь вычислить произведение матрицы на вектор. Хотя матрица содержит дроби, результирующие коэффициенты будут целыми числами, так что вычисления можно вести в целочисленной арифметике путём сложения, вычитания и умножения/деления на маленькие константы. Здесь основной задачей является поиск эффективной последовательности операций, позволяющей вычислить произведение матрицы на вектор. Одну такую последовательность дал Бодрато[6] для Тоом-3 и она для нашего примера следующая:

      = 3084841486175176
      = 12193131840
      = (3188843994597408 − 13260814415903778)/3
= −3357323473768790
      =  
= 6753544154624910
      =  
= −3331115379521218
      =  
= 13128433387466
      = −3331115379521218 + 6753544154624910 − 12193131840
= 3422416581971852
      = 6753544154624910 − 13128433387466
= 6740415721237444.

Мы теперь знаем произведение r наших многочленов:

 

Если бы мы использовали другие   или выбрали другие точки для вычисления значений, матрица, а тогда и стратегия интерполяции, изменилась бы, но это не зависит от входных данных, а потому алгоритм может быть зашит «в железе» для любых данных параметров.

Рекомпозиция

править

Наконец, мы вычисляем r(B) для получения конечного результата. Это выполняется напрямую, поскольку B является степенью b, а потому умножение на степени B является сдвигом всего числа на целое число знаков основания b. В нашем примере   и  .

3084 8414 8617 5176
6740 4157 2123 7444
3422 4165 8197 1852
13 1284 3338 7466
+ 121 9313 1840

121 9326 3124 6761 1632 4937 6009 5208 5858 8617 5176

Результатом является произведение 1234567890123456789012 и 987654321987654321098.

Матрицы интерполяции для различных значений k

править

Здесь мы приведём матрицы интерполяции для нескольких различных малых значений   и  .

Тоом −1

править

Тоом-1 ( ) требует вычисления в одной точке, здесь выбирается 0. Алгоритм вырождается в умножение в столбик с единичной матрицей интерполяции:

 

Тоом-1.5

править

Тоом-1.5 ( ) требует две точки, здесь выбраны 0 и  . Матрица интерполяции тогда равна единичной матрице:

 

Алгоритм также вырождается в умножение в столбик — оба коэффициента одного множителя умножается на один коэффициент другого множителя.

Тоом-2 ( ) требует трёх точек, здесь выбраны 0, 1 и  . Алгоритм получается тем же, что и алгоритм Карацубы с матрицей интерполяции:

 

Тоом-2.5

править

Тоом-2.5 (  требует 4 точки, здесь выбраны 0, 1, −1 и  . Алгоритм тогда имеет матрицу интерполяции:

 

Примечания

править
  1. 1 2 Knuth, 1997, с. 296.
  2. Crandall, Pomerance, 2005, с. 474.
  3. Crandall, Pomerance, 2005, с. 536.
  4. Knuth, 1997, с. 302.
  5. Positive Results Архивная копия от 6 января 2013 на Wayback Machine, chapter III of Stephen A. Cook: On the Minimum Computation Time of Functions.
  6. 1 2 3 Bodrato, 2007, с. 116–133.

Литература

править
  • D. Knuth. Section 4.3.3.A: Digital methods // The Art of Computer Programming. — Third Edition. — Addison-Wesley, 1997. — Т. 2. — С. 294.
  • Кнут Д.Э. Искусство программирования. Получисленные алгоритмы. — 2019. — Т. 2. — ISBN 978-5-907144-15-6.
  • R. Crandall, C. Pomerance. Section 9.5.1: Karatsuba and Toom–Cook methods // Prime Numbers – A Computational Perspective. — Second Edition. — Springer, 2005. — С. 473.
    • Ричард Крэндалл, Карл Померанс. Простые числа. Криптографические и вычислительные аспекты. — Москва: Либроком, 2011. — ISBN 978-5-397-02060-2.
  • M. Bodrato. Toward Optimal Toom–Cook Multiplication for Univariate and Multivariate Polynomials in Characteristic 2 and 0 // Arithmetic of Finite Fields. — Springer, 2007. — Т. 4547. — (LNCS).

Ссылки

править