Разобрался с первой реализацией is_not_zero().
unsigned int is_not_zero(unsigned int x)
{
unsigned int zero = 0;
unsigned int ones = ~zero;
unsigned int hi_one = (ones / 2) + 1;
unsigned int t = (x & -x) * ones;
return (t & hi_one) / hi_one;
}
unsigned int is_zero(unsigned int x)
{
return 1 - is_not_zero(x);
}
Без бумажки с ручкой и комментариев, мне опыта не достаёт понимать Ваш код. :)
На число наложим маску того же числа, только в дополнительном коде. Интересная конструкция. Мы так выделяем один бит для ненулевого числа.
Тут мы число с выделенным битом умножаем на 0xFFFF (опустим для упрощения размеры int), что даёт нам 0xFFFF в случае ненулевого числа. Для нуля же будет нулевой результат.
Наложили маску 0x8000 (размерами int опять пренебрегли) и выделили старший бит в
. Если он установлен, то при делении на 0x8000 мы получим
, если сброшен, то
(ведь деление целочисленное).
Иными словами, если входная переменная равна нулю, то на выходе мы получим нуль, иначе единицу.
unsigned int is_zero(unsigned int x)
{
return 1 - is_not_zero(x);
}
Тут я, по простоте своей, делал бы инверсию результата от is_not_zero(), а потом бы снова маску применял. Ваше решение лучше.
Пошёл следующую функцию разбирать.
Вывод шестнадцатеричных чисел с помощью тега math выглядит не очень, поэтому я его не использовал тут, но если надо переделаю.