Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 [ 55 ] 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

Таким образом, если в таблице имеются делители 3, 5, 25, то могут быть обработаны делители 6, 10, 100 и т.д.

Такая процедура обычно дает наименьшее магическое число, хотя и не всегда. Если размер слова равен 32 бита, то наименьший положительный делитель, когда такое происходит, равен 334972. Данный метод при этом дает значения т=3361176179 и s=18; минимальное же магическое число для данного делителя составляет 840294045, а величина сдвига равна 16. Процедура также дает неминимальный результат при d = -6. В обоих приведенных случаях снижается качество генерируемого кода деления.

Алверсон [2] был первым, кто указал на корректность работы описываемого далее метода для всех делителей. Используя наши обозначения, можно сказать, что его метод для беззнакового целого деления на d состоит в использовании величины сдвига p = W+[logjt/] и множителя т= I/d с последующим выполнением деления

nd = mn/2 (т.е. путем умножения и сдвига вправо). Он доказал, что множитель т

меньше г** и что этот метод дает точное значение частного для всех п, выражаемых с помощью W-битового числа.

Метод Алверсона представляет собой более простой вариант нашего, в котором для определения р не используется поиск методом проб и ошибок, а следовательно, он в большей степени подходит для аппаратной реализации, в чем и состоит его главное назначение. Однако его множитель т всегда оказывается не меньшим, чем 2*, а потому при программной реализации всегда требуется код, проиллюстрированный в примере деления на 7 (т.е. всегда требуются либо команды add и shrxi, либо четыре альтернативные команды). Поскольку большинство небольших делителей могут быть обработаны при помощи множителей, меньших 2*, представляется разумным рассмотреть эти случаи.

В случае знакового деления Алверсон предложил искать множитель для \d\ и длины

слова W -1 (тогда г"" < m < 2* ), умножать на него делимое и, если операнды имеют противоположные знаки, изменять знак полученного результата. (Множитель должен быть таким, чтобы давать корректный результат для делимого г*", которое представляет собой абсолютное значение максимального отрицательного числа). Похоже, что такое предложение может дать код, лучший по сравнению с кодом для множителя таг*. Применяя данный прием к знаковому делению на 7, получим следующий код (где для того, чтобы избежать ветвления, использовано соотношение ~х = х + \):

abs an,n

li М,0x92492493 Магическое число (2**34+5)/7

mulhu q,M,an q = floor(M*an/2**32) shri q,q,2

shrsi t,n,31 Эти три команды

xor q,q,t изменяют знак q,

sub q,q,t если n отрицательно

Этот код не столь хорош, как тот, который был предложен для знакового деления на 7 ранее (7 и 6 команд соответственно), но он может оказаться полезным на компьютере, у которого есть команды abs и mulhu и нет команды mulhs.

10.13. ДРУГИЕ ПОХОЖИЕ МЕТОДЫ 185



Таблица 10.1. Некоторые магические числа для W = 32

Знаковое

Беззнаковое

М (шестнадцатеричное)

М (шестнадцатеричное)

99999999

55555555

7FFFFFFF

80000001

232-к

55555556

АААААААВ

66666667

CCCCCCCD

2ААААААВ

АААААААВ

92492493

24924925

38Е38Е39

38Е38Е39

66666667

CCCCCCCD

2Е8ВА2Е9

BA2E8BA3

2ААААААВ

АААААААВ

51EB851F

51EB851F

10624DD3

10624DD3

68DB8BAD

D1B71759

Таблица 10.2. Некоторые магические числа для W = 64

Знаковое

Беззнаковое

М (шестнадцатеричное)

М (шестнадцатеричное)

99999999

99999999

55555555

55555555

7FFFFFFF

FFFFFFFF

80000000

00000001

2б4-к

55555555

55555556

АААААААА АААААААВ

66666666

66666667

СССССССС CCCCCCCD

2ААААААА

АААААААВ

АААААААА АААААААВ

49249249

24924925

24924924 92492493

1С71С71С

71С71С72

Е38Е38ЕЗ 8E38E38F

66666666

66666667

СССССССС CCCCCCCD

2Е8ВА2Е8

ВА2Е8ВАЗ

2Е8ВА2Е8 ВА2Е8ВАЗ

2ААААААА

АААААААВ

АААААААА АААААААВ

A3D70A3D

70A3D70B

47АЕ147А Е147АЕ15

20С49ВА5

E353F7CF

0624DD2F 1A9FBE77

346DC5D6

3886594В

346DC5D6 3886594В

10.15. Точное деление на константу

Под "точным делением" подразумевается деление, о котором заранее известно, что его остаток равен 0. Хотя такая ситуация и не очень распространена, она имеет место, например при вычитании двух указателей в языке С. В нем результат вычитания p-q, где рид - указатели, определен и переносим, только если рид указывают на объекты в



одном и том же массиве [32, раздел 7.6.2]. Если размер элемента массива равен s, то код для вычисления разности двух указателей реально вычисляет {p-q)/s.

Материал этого раздела основан на [21, ра:дел 9].

Рассматриваемый здесь метод применим как к знаковому, так и к беззнаковому точному делению и базируется на следующей теореме.

Теорема Ml. Если а и т - взаимно простые целые числа, то существует целое число 1<айт, такое, что аа sl(nMxlm).

Таким образом, а представляет собой обратный мультипликативный по модулю т элемент по отнощению к а. Есть несколько способов доказательства этой теоремы, три из них описаны в [49]. Доказательство, приведенное далее, требует только знания основ теории сравнений.

Доказательство. Докажем более общее по сравнению с данной теоремой утверждение. Если ант взаимно просты (и, следовательно, имеют ненулевые значения), то для множества jc, состоящего из т различных по модулю т значений, значения ах также будут различны по модулю т. Например, при а = 3 ит = 8 и значениях jc из диапазона от О до 7 получим, что значения ах представляют собой множество О, 3, 6, 9, 12, 15, 18, 21, или по модулю 8 это числа О, 3, 6, 1, 4, 7, 2, 5. Заметим, что в полученной последовательности вновь представлены все числа от О до 7.

Чтобы доказать это в общем случае, воспользуемся методом доказательства от противного. Предположим, что существуют два различных по модулю т целых числа, которые отображаются в одно и то же число по модулю т при умножении на а, т.е. существуют такие jc и у (л: * у (mod m)), что ах s ау (mod m). Но в таком случае существует целое

число к, такое, что

ах-ау = кт , или а{х-у) = кт.

Поскольку а не имеет общих множителей с т, разность х-у должна быть кратной т, т.е.

д:н y(mod m).

Однако этот вывод противоречит исходному предположению.

Теперь, поскольку значения ах принимают все т возможных различных значений по модулю т, среди значений jc найдется такое, для которого ах по модулю т равно 1.

Приведенное доказательство показывает также, что имеется только одно значение jc (по модулю т), такое, что ax = l(madm), т.е. что мультипликативное обращение однозначно. Можно также показать, что имеется единственное (по модулю т) целое число jc, такое, что ах s Ь{пюй т), где Ь - любое целое число.

В качестве примера рассмотрим случай т = 16.Тогда 3 = 11,так как 311 = 33 = l(modl6). Можно также считать, что 3=-5, поскольку 3(-5) = -15 = l(nMdl6). Аналогично, -3 = 5, поскольку (-3) • 5 = -15 S l(mod 16).

Важность этих наблюдений заключается в том, что они показывают применимость рассматриваемых концепций как к знаковым, так и к беззнаковым числам. Если вы будете работать с беззнаковыми числами на 4-битовой машине, то получите 3 = 11; если же



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 [ 55 ] 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87