Анимация
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.2. Округление к ближайшей степени 2

Определим функции flp2(jc) и clp2(jc), которые округляют число х к ближайшей целой степени 2, следующим образом:

х<0,

Пр2{х) = \ О, х = 0, clp2(i:) =

не определена, х<0, О, х = 0,

2"К х>0;

не определена, х < О,

О, х = а

2°""\ х>0.

Значение функции flp2(x) представляет собой наибольшую целую степень 2, не превосходящую значение х, а функции с1р2(х) - наименьшую целую степень 2, не меньшую, чем X. Эти определения имеют смысл и для нецелых х (например, flp2(0.1) = 0,0625). Эти функции удовлетворяют ряду отношений, аналогичных отношениям между функциями floor(x)sLxJ и ceil(x) 2 [х], в частности приведенным ниже.

[xJ = ("х] , только если х - целое Яр2(х) = с1р2(х), только если х - степень 2 или О

lx + nj = [x} + n flp2(2"x) = 2"flp2(x)

rxl = -L-xJ clp2(x) = l/flp2(l/x), xO

При вычислениях используются только целые беззнаковые жачения х, так что обе функции определены для любых возможных значений х. Кроме того, используется требование, чтобы вычисленное значение представляло собой значение по модулю 2 (таким образом, с1р2(х) = О прих>2). Далее представлены значения функций для некоторых значенийх.

Пр2{х)

с1р2(х)

231 + 1

функции flp2(x) и с1р2(х) связаны между собой определенными соотношениями, которые позволяют вычислить значения одной функции из значений другой (с учетом указанных ограничений).

flp2(x)=i

1<х<2",

с1р2(х) =

2flp2 flp2(2x-

х-1 1

с1р2 с1р2(,

х+2 + 1

х*0, х<2".



функции округления в большую и меньшую сторону можно достаточно легко вычислить с помощью функции, вычисляющей количество ведущих нулевых битов, как показано ниже. Однако, чтобы эти формулы можно было использовать для х=0 и х>2, команды сдвига на вашем компьютере должны давать О при сдвиге на величины -1, 32 и 63. На многих машинах (например, PowerPC) есть команда "сдвига по модулю 64", которая работает именно так. Отрицательный сдвиг эквивалентен сдвигу в противоположном направлении (т.е. сдвиг влево на-1 - это просто сдвиг вправо на 1).

flp2(x) = l<e(31-nlz(x)) = = l<e(nlz(x)®3l) =

= 0x80000000»nlz(x)

clp2(x) = l<e(32-nlz(i:-l)) =

= 0x800000003>(nlz(x -1) -1)

Округление в меньшую сторону

В листинге 3.1 приведен алгоритм без ветвления, который полезен в случае отсутствия функции, вычисляющей количество ведущих нулевых битов. Алгоритм основан на распространении вправо крайнего слева единичного бита и требует для реализации выполнения 12 команд.

Листинг 3.1. Наибольшая степень 2, ие превосходящая значение х

unsigned f1р2(unsigned х) {

X = X

>>

X = X

>>

X = X

>>

4) ;

X = X

>>

X = X

>>

16);

return

X -

» X) ;

в листинге 3.2 показаны два простых цикла, вычисляющих одну и ту же функцию. Все переменные в приведенных фрагментах представляют собой беззнаковые целые числа. Цикл справа обнуляет крайний справа единичный бит переменной х до тех пор, пока она не становится равной О, после чего возвращается предыдущее значение х.

Листинг 3.2. Округление х в меньшую сторону

у = 0x80000000; do {

While (у > X) у = х;

у = у » 1; X = X & (Х - 1) ;

return У; } while(X != 0);

return у;

При вычислении левого фрагмента требуется 4п1г(лг)+3 команды; цикл справа при хО требует выполнения 4рор(ж) команд, если сравнение с О имеет нулевую стоимость.

Функция pop(jc) возвращает количество единичных битов в х . 3.2. ОКРУГЛЕНИЕ К БЛИЖАЙШЕЙ СТЕПЕНИ 2 59



Округление в большую сторону

Использование распространения старшего бита вправо дает хороший алгоритм для округления к ближайшей большей степени 2. Представленный в листинге 3.3 алгоритм не имеет команд ветвления и вьшолняется за 12 команд.

Листинг 3.3. Наименьшая степень 2, не уступающая значению х

unsigned с1р2(unsigned х) {

X = X - 1;

X = X

X = X

X = X

X = X

X = X

return X + 1;

(X » 1)

(X » 2)

(X » 4)

(X >> 8)

(X » 16) ;

Попытка провести вычисление с использованием цикла работает не так хорошо, как хотелось бы. У = 1;

while (у < х) Беззнаковое сравнение

У = 2*у; return у;

Для х=0 данный алгоритм дает 1, что не совсем то, что требуется; а при х>2 происходит зацикливание. Вычисления требуют выполнения 4и+3 команд, где п - степень 2 возвращаемого кодом числа. Таким образом, этот алгоритм будет работать медленнее алгоритма без ветвления уже при и>3 (т.е. придг>8),

3.3. Проверка пересечения границы степени 2

Предположим, что вся память разделена на блоки, причем размер каждого блока представляет собой степень 2. Нумерация адресов начинается с 0. Блоки могут быть словами, двойными словами, страницами и т.д. Пусть дан некоторый начальный адрес а и длина /. Требуется определить, пересекает ли диапазон адресов от а до а+Z -1, />2, границы блока или нет (величины а и / - целые беззнаковые, полностью размещаемые в регистрах).

Если ;=0 или 1, то, независимо от значения а, пересечения границ блока не будет. Если / превышает размер блока, то, каким бы ни было значение а, произойдет выход за границы блока. Для очень больших значений / (с возможным циклическим возвратом) выход за границы блока может произойти, даже если первый и последний байты диапазона адресов расположены в одном блоке.

Для ЮМ System/370 определить, произойдет ли выход за границы блока, оказывается на удивление просто [7]. Вот как этот метод работает для размера блока, равного 4096 байт (стандартный размер страницы).

о RA-, =А(-40Э6)

ALR RA,RL ВО CROSSES

В первой команде над регистром RA (в котором содержится начальный адрес а) и числом OxFFFFFOOO выполняется команда побитового или. Вторая команда добавляет к



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