|
|
|
| Как сделать циклический сдвиг (аналог ROL/ROR) в PHP ?
Делаю так, не работает :(
function ROL($value, $shift)
{
$sft = $shift & 0x1F;
return ($value << $sft) | ($value >> (32 - $sft));
} | |
|
|
|
|
|
|
|
для: php_user
(14.01.2009 в 19:59)
| | правый сдвиг знакового целого требует дополнительного маскирования старших разрядов. У Вас этого нет. | |
|
|
|
|
|
|
|
для: php_user
(14.01.2009 в 19:59)
| | Что не работает? Вообще-то в РНР нет циклического сдвига, так как это делают вышеуказанные команды процессора. Вы об этом? | |
|
|
|
|
|
|
|
для: sim5
(14.01.2009 в 20:16)
| | там проще всё. На числах с установленным в 1 старшим битом эта функция будет давать сбой.
Там изменить-то всего чуть. | |
|
|
|
|
|
|
|
для: Trianon
(14.01.2009 в 20:41)
| | Да я не об этом, я смотрю, что атор хочет добиться аналога команд, а эти команды производят то циклический сдвиг, РНР то ведь этого не делает. | |
|
|
|
|
|
|
|
для: sim5
(14.01.2009 в 20:45)
| | Так этого не делает ни php, ни С, ни java . Но это ж не значит что нельзя представить такую операцию.
Скобки в первом посте стоят так, что не позволяют заподозрить автора во мнении что, php эту операцию поддерживает. | |
|
|
|
|
|
|
|
для: Trianon
(14.01.2009 в 20:41)
| | >> На числах с установленным в 1 старшим битом эта функция будет давать сбой.
>там проще всё. На числах с установленным в 1 старшим битом эта функция будет давать сбой.
>Там изменить-то всего чуть.
И что, надо проверять старший бит? Не хотелось бы с условиями делать... | |
|
|
|
|
|
|
|
для: php_user
(14.01.2009 в 20:46)
| | да нет, не надо...
Хотя, нет. пожалуй, условная операция понадобится так или иначе.... | |
|
|
|
|
|
|
|
для: Trianon
(14.01.2009 в 20:48)
| | Спасибо большое!
Все работает!
function ROL($value, $shift)
{
$sft = $shift & 0x1F; // чтобы учитывались только младшие 5 разрядов
return ($value << $sft) | (($value >> (32 - $sft)) & ((1 << (31 & $sft)) - 1)) ;
} | |
|
|
|
|
|
|
|
для: php_user
(14.01.2009 в 20:59)
| | Не работает.
При $sft = 31 будет сбой.
А может не будет. Выход за разрядную сетку будет точно. | |
|
|
|
|
|
|
|
для: Trianon
(14.01.2009 в 21:00)
| | Может делать выборку маски из массива ? | |
|
|
|
|
|
|
|
для: php_user
(14.01.2009 в 21:19)
| | на ассемблере вариант с векторизацией был бы самым быстрым. На php - сомнительно.
((((1<<($sft -1))-1)<<1)|1)
при sft = 0 вообще аргумент не нужно дергать.
надо измерять быстродействие и выбирать самый шустрый вариант.
И кстати, стоит убедиться что для 64-разрядного php еще чего не выползет. | |
|
|
|
|
|
|
|
для: Trianon
(14.01.2009 в 21:25)
| | для проверки сделал так
function ROL($value, $shift)
{
$sft = $shift & 0x1F;
if ($sft == 31) { echo $sft; }
return ($value << $sft) | (($value >> (32 - $sft)) & ((1 << (31&$sft)) - 1) ) ;
}
В процессе обработки масива из ~4000 32-хразрядных элементов сдвиг на 31 проскакивал несколько десятков раз. Тем не менее все обработалось правильно...
С вариантом ((((1<<($sft -1))-1)<<1)|1) так же...
Для сравнения по быстродействию сделал
echo microtime() . "<br>\r\n";
$x = 0x12345678;
$y = 0;
for ($i=0; $i<1000000; $i++)
{
$y = $y | ROL($x, $i);
}
echo microtime() . "<br>\r\n";
die("result = " . $y);
1-й, 2-й варианты и вариант с массивом (глобальным) выполняются примерно одинаково за 4 сек. | |
|
|
|
|
|
|
|
для: sim5
(14.01.2009 в 20:16)
| | В том-то и дело, что нету :( Стало быть надо сделать функцию аналог...
Как и сказал Trianon, дело оказалось в маскировании старших разрядов при сдвиге вправо, сейчас разбираюсь с этим... | |
|
|
|