ViKo 1 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8. В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего. Как это сделать макрофункцией? Тогда я смогу задавать сдвиг "магических чисел" в регистре по имени группы битов в этом регистре. P.S. Обратная функция легко делается сдвигом 1 << NUM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ae_ 2 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Для одного бита: log2(0x0100)=8 Не скажу за все препроцессоры, но AVRASM2 понимает такое LOG2(0x0100) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gosha-z 2 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Хочу, например, для числа 0x0100 найти позицию бита, который в 1, то есть, получить число 8. В-принципе, этот бит будет один (младший бит в группе), но если их несколько, нужно определить позицию младшего. Как это сделать макрофункцией? Что-то в голову ничего, кроме вариаций на тему условного rvalue, не приходит. P.S. Обратная функция легко делается сдвигом 1 << NUM. Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Для этих целей есть Find First Set (ffs). Или вот ещё -> "Number of leading zeros algorithms" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Вот нифига. AFAIR, стандарт не определяет используемый тип сдвига, арифметический или круговой. Так что результат, скорее, неопределенный, если не маскировать специально. Шутки шутите? Э, да ведь можно с помощью #if перебрать все варианты! #if (VAL == 0x8000) #define NUM 15 #elif (VAL == 0x4000) #define NUM 14 ... А еще проще через лестницу тернарных операторов. :yeah: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 6 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба А еще проще через лестницу тернарных операторов. :yeah: о, а это хорошая идея. Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции //calc position of rightmost nonzero bit #define m2b(x) (\ (((x & -x) & 0x0000FFFF) ? 0 : 16)+\ (((x & -x) & 0x00FF00FF) ? 0 : 8)+\ (((x & -x) & 0x0F0F0F0F) ? 0 : 4)+\ (((x & -x) & 0x33333333) ? 0 : 2)+\ (((x & -x) & 0x55555555) ? 0 : 1)+\ ((x & -x) ? 0 : 1)) Плюс в том, что это макроопределение можно использовать прямо внутри выражения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Правильно ли я понял: допустим у вас есть #define MASK 0x000FF0 И вы хотите из этого MASK получить 4 чтобы сделать Reg = N << 4; Можно сделать (я делаю) так: Reg = N * (MASK & -MASK); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Правильно ли я понял:... Да, правильно. Спасибо! Супер. И ведь видел когда-то... :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 августа, 2014 Опубликовано 29 августа, 2014 · Жалоба Если описать конкретно младший бит в группе, то можно пользоваться тем же умножением, что я и сам делаю ( показывал в другой теме). Только сомножители местами переставлены. :rolleyes: Reg |= N * MASK_0; Компилятор все эти умножения на сдвиги заменяет, естественно. Есть такой алгоритм, приличный С-компилятор должен это вычислить во время компиляции ... Плюс в том, что это макроопределение можно использовать прямо внутри выражения. Да, спасибо, макро работает, компилируется в число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 178 16 августа, 2023 Опубликовано 16 августа, 2023 · Жалоба Случайно нагуглил тему. Может пригодится кому-нибудь: __builtin_ctz() и его друзья. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 28 сентября, 2023 Опубликовано 28 сентября, 2023 · Жалоба On 8/28/2014 at 11:26 PM, Сергей Борщ said: Можно сделать (я делаю) так: Reg = N * (MASK & -MASK); Тут ошибка? У нас такое выражение используется для установки полей по маске: (REG & ~MASK) | (N * (MASK & ~(MASK << 1)) & MASK) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 28 сентября, 2023 Опубликовано 28 сентября, 2023 · Жалоба 10 минут назад, Lagman сказал: Тут ошибка? У меня работает... MASK = 0xF0, 5 * (0xF0 & 0xFFFFFF10) = 5 * 0x10 = 0x50, что и требовалось. 10 минут назад, Lagman сказал: У нас такое выражение используется для установки полей по маске: У вас другое выражение - в нем инверсия, в моем отрицательное число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 28 сентября, 2023 Опубликовано 28 сентября, 2023 (изменено) · Жалоба Я ни в каких либах не видел такого извращения. Везде явно задают маски и позиции полей. (например через имена вида х_Msk, x_Pos) Сделать конешн можно, но после препроцессинга оно развернется в дикую дичъ. под стать плюсовым шаблонам. Имхо, это плохой путь. Или понадобилось нечто особенное? Я тэту задачу решал такими макро: // @brief is low n-bits clear #define IS_CTZn(x, n) ( ((x) & ((1<<(n))-1)) == 0 ) #define CTZ_1(n) ( IS_CTZn((n), 1) ? 1 : 0) #define CTZ_2(n) ( IS_CTZn((n), 2) ? (2 + CTZ_1((n)>>2)) : CTZ_1(n)) #define CTZ_4(n) ( IS_CTZn((n), 4) ? (4 + CTZ_2((n)>>4)) : CTZ_2(n)) #define CTZ_8(n) ( IS_CTZn((n), 8) ? (8 + CTZ_4((n)>>8)) : CTZ_4(n)) #define CTZ(n) ( IS_CTZn((n), 16) ? (16 + CTZ_8((n)>>16)) : CTZ_8(n) ) Мне оно зашло лучше чем использование (x & -x), ибо позволяет работать с unsigned без сюрпризов Изменено 28 сентября, 2023 пользователем AlexRayne Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 28 сентября, 2023 Опубликовано 28 сентября, 2023 · Жалоба В 28.08.2014 в 19:14, SSerge сказал: ((x & -x) ? 0 : 1)) Плюс в том, что это макроопределение можно использовать прямо внутри выражения. тут нужно еще Х скобками обернуть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 28 сентября, 2023 Опубликовано 28 сентября, 2023 · Жалоба 1 час назад, AlexRayne сказал: Мне оно зашло лучше чем использование (x & -x), ибо позволяет работать с unsigned без сюрпризов Аналог -x очень прост: ~(x)+1u Если надо без знаковости... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться