Написать a = (a == b ? 0 : a) без ветвлений

Тема в разделе "LANGS.C", создана пользователем Ation, 6 июл 2010.

  1. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
     
  2. skomarov

    skomarov New Member

    Публикаций:
    0
    Регистрация:
    14 май 2008
    Сообщения:
    389
    J0E
    Все-таки существует разница между операцией сравнения "!=" (не равно) и операцией логического НЕ "!", которая только эквивалентна сравнению с нулем, иначе можно дойти до того, чтобы назвать операцию побитовое И "&" циклом с набором побитовых сравнений.

    google
    Пусть решит автор темы.
     
  3. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Стандарт пишет: "The expression !E is equivalent to (0==E)."
    == запрещено :) Так можно дойти, что equivalent это не "равноценный, равнозначащий; равносильный; равнозначный, эквивалентный"
     
  4. skomarov

    skomarov New Member

    Публикаций:
    0
    Регистрация:
    14 май 2008
    Сообщения:
    389
    J0E
    В таком случае получается, что нельзя использовать логические операции И "&&", ИЛИ "||", которые также производят сравнение с нулем.
    Следующие решения не проходят это ограничение:
    Код (Text):
    1. a*=((a^b) || 0)
    2. a*=((a^b) && 1)
    3.  
    4. a&=-((a^b) || 0)
    5. a&=-((a^b) && 1)
     
  5. Ation

    Ation New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2005
    Сообщения:
    92
    Адрес:
    Zaporozhie
    Спасибо всем отписавшимся.
    Попробую точнее сформулировать. Смысл вопроса был в том, что надо избежать любых логических операций (>, < , ==, !=), которые неминуемо порождают ветвления (я не имею ввиду явную форму), что может привести к сбросу конвеера.
    И интересно было именно решение на С, т.к. будет действительным для большего количества архитектур )
    Вариант от google
    Код (Text):
    1. a &= ((signed)((a-b) | (b-a)) >> sizeof(a)*8)
    отлично выполняет условия.
    Вариант от skomarov элегантен,
    Код (Text):
    1. a &= (!(a^b)-1);
    но не выполняет основной задачи. С такиж же успехом можно писать и a = (a == b ? 0 : a), и a *= (a != b), и так далее.
     
  6. skomarov

    skomarov New Member

    Публикаций:
    0
    Регистрация:
    14 май 2008
    Сообщения:
    389
    Ation
    А ассемблерный код в сообщении #18 приводит к сбросу конвейера?
     
  7. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Ation - там ошибка, надо (sizeof(a)*8-1)
    Возникает вопрос, а чего тогда сразу не написать:
    Код (Text):
    1. mov   ebx, [a]
    2. xor   eax, eax
    3. cmp   ebx, [b]
    4. movne eax, ebx
    х86 не единственная в мире, и далеко не на всех архитектурах есть аналоги SETcc и MOVcc.
     
  8. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Да, ведь это явное ветвление, в силу ленивости операций. Но они и не нужны, можно обойтись чистой арифметикой, см вариант google который отлично понял что я имел ввиду в первом посте (хотя может и не смотрел его). А еще "потенциально нельзя" использовать другие команды, которые могут давать ложные зависимости по данным (MOVcc, SBB) не понятно почему автора темы волнует исключительно сброс конвейера, раз он считает себя умнее компилятора.
     
  9. skomarov

    skomarov New Member

    Публикаций:
    0
    Регистрация:
    14 май 2008
    Сообщения:
    389
    Может быть, мы сами усложняем простые условия автора? :) Правда, это хорошо в целях обучения.