- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
inline int8_t log2(size_t value)
{
static constexpr int8_t table[64] =
{
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5
};
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
return table[((value - (value >> 1)) * 0x07EDD5E59A4E28C2) >> 58];
}
Случайно наткнулся на такую магию.
Вроде проще способ был - без массивов и плясок с умножением на магическую константу с переполнением.
j123123 06.03.2017 21:51 # 0
https://en.wikipedia.org/wiki/Find_first_set#Tool_and_library_support
https://www.go4expert.com/articles/builtin-gcc-functions-builtinclz-t29238/
https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
Built-in Function: int __builtin_clz (unsigned int x)
Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
Built-in Function: int __builtin_clzl (unsigned long)
Similar to __builtin_clz, except the argument type is unsigned long.
Built-in Function: int __builtin_clzll (unsigned long long)
Similar to __builtin_clz, except the argument type is unsigned long long.
bormandinho 06.03.2017 22:47 # −1
Сдвиги забивают все младшие биты единицами.
0b00010101 превращается в
0b00011111.
Разность оставляет установленным только один бит:
0b00011111
-
0b00001111
=
0b00010000
Итого: сдвиги и разность оставляют единичным только самый старший единичный бит, остальные обнуляют.
Умножение на магическую константу числа, у которого установлен только один бит, эквивалентен сдвигу магической константы.
0b00010000 * 0x07EDD5E59A4E28C2 == 0x07EDD5E59A4E28C2 << 4.
Для произвольного value получим 0x07EDD5E59A4E28C2 << log_2(value).
Двигая 64-битное число вправо на 58, мы оставляем только 6 старших битов.
Т. е. все эти манипуляции вырезают из 0x07EDD5E59A4E28C2 шесть смежных битов. Положение вырезанного куска зависит от log_2(value). А дальше происходит выборка из таблицы.
Почему нельзя было объявить магическую константу вроде 0xFEDBCA986543210 (тогда бы и таблица не понадобилась) и использовать сдвиги, кратные четырём? Потому что 64-битной константы не хватит для хранения 64 значений (мы в неё сможем затолкать только 16). Значит, нужно либо использовать 64*6=384-битную константу, либо... придумать алгоритм зожатия, что здесь и было продемонстрировано.
Antervis 07.03.2017 06:10 # +2
inline int8_t log2(size_t value)
Да ну?
j123123 07.03.2017 13:15 # +2
bormandinho 06.03.2017 22:29 # +8
Вот так легче читается.
inho 06.03.2017 22:37 # 0
Antervis 07.03.2017 07:15 # +7
dxd 07.03.2017 07:33 # 0
bormandinho 07.03.2017 11:11 # 0
Ну ладно, исправил:
HACTEHbKA 07.03.2017 22:23 # +1
http://govnokod.ru/22508
милый Борманд жду тибя
TheCalligrapher 07.03.2017 00:23 # +3
Разумеется, в системе команд процессоров интеловского семейства (да и других тоже) уже давно появились встроенные команды для решения этой задачи, на к которым в компиляторах привязаны соответствующие нестандартные средства: `_BitScanReverse64` в MSVC и `__builtin_clzll` в GCC. Но, разумеется, использование этих нестандартных свойств без предоставления fallback implementation не допускается: это будет классикой жырного говнокодинга. Вышеприведенный вариант как раз является хорошим вариантом fallback implementation.
Так что эту заявку на говнокод я вынужден отклонить. Учите матчасть.
guest 07.03.2017 00:52 # +3
Вот ты меня унизил сейчас.
bayan 07.03.2017 00:53 # +3
надо было сделать вид что ты знаешь что такое последовательность де Брёйна.
Дескать: "ах, да я каждый день с ней сталкиваюсь когда пишу валидаторы формочек на JS"
hasOwnProperty 07.03.2017 00:57 # 0
bayan 07.03.2017 00:58 # +2
j123123 07.03.2017 02:53 # +1
Нет, не соглашусь. Я считаю что наилучшим вариантом будет втулить туда все возможные нестантартные интринсики через #ifdef директивы препроцессора, а если ничего из этого по каким-либо причинам не подходит, надо чтобы это просто не собиралось. И тогда уже пусть программист пилит там себе реализацию. Поясню:
Если никакие интнинсики не подошли, скорее всего кто-то это собирает под какую-то нестандартную платформу каким-то нестандартным компилятором, например это вполне может оказаться какой-нибудь AVR микроконтроллер. Если это окажется AVR микроконтроллер без поддержки инструкций умножения, то вышеозначенная fallback implementation, использующая умножение, скорее всего развернется в очень жирный и неэффективный машинный код, что может быть критично для микроконтроллера, и лучше бы под этот случай написать другую fallback implementation, например через какие-нибудь сдвиги, или же вообще на ассемблерных вставках
guest 07.03.2017 02:56 # 0
astandj <a href= http://buyviagra24ph.com >generic viagra</a>
Antervis 07.03.2017 06:11 # +1
case dismissed
roman-kashitsyn 07.03.2017 13:23 # −1
Ого, давненько вас не было видно. Заходите почаще, а то доля интересного чтива на сайте стремится к нулю на фоне разбушевавшихся ботов.
bayan 07.03.2017 00:49 # 0
http://cdn.intechopen.com/pdfs-wm/5296.pdf
bayan 07.03.2017 01:03 # −1
Знаете?
hasOwnProperty 07.03.2017 01:05 # 0
bayan 07.03.2017 01:05 # +1
погугли "0x5f3759df"
hasOwnProperty 07.03.2017 01:17 # 0
А история-то в чём?
bayan 07.03.2017 01:19 # 0
что "волшебная" константа позволяет примерно посчитать обратный корень быстрее чем на fpu
hasOwnProperty 07.03.2017 01:23 # 0
bayan 07.03.2017 01:53 # 0
я в математике слаб
guest 07.03.2017 02:06 # +1
> сомнительный битодроч
bayan 07.03.2017 02:08 # 0
guest 07.03.2017 01:08 # 0
bayan 07.03.2017 01:10 # +1
gost 07.03.2017 13:26 # +2
> value |= value >> 32;
Ай! Нога!
guest 07.03.2017 14:05 # 0