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

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

  1. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    skomarov
    Убедили:)
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Не работает. Зачем >> sizeof(a)*8?
     
  3. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Знаковый разряд расширяется. Если хотя бы одна из разностей отрицательная (т.е. числа различаются), >> sizeof(a)*8 даст в результате 0xFFFFFFFF.
     
  4. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    "хотя бы" следует вычеркнуть
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Может тогда: >> (sizeof(a)*8 - 1)?
    sizeof(a)*8 возвращает прежнее число.
     
  6. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Booster
    Да, так правильнее. Но результат будет одинаков. Команда sar не циклическая же.
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Не знаю как у вас, у меня циклическая. ^)
     
  8. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Циклическая это ROR, а SAR нет.

    К стати вариант с != не подходит под расплывчатые условия.
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    J0E
    Я не про то, что она циклическая как ROR. А про то, что sar eax, 32 эквивалентна sar eax, 0.
     
  10. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Booster
    Код который я привел, я тестировал. Все прекрасно работает. Но не по предполагаемой мной причине, а потому что компилятору от MS без разницы что написано в исходном коде, оба варианта (>> sizeof(a)*8 и >> (sizeof(a)*8-1)) приводятся к виду sar reg, 31.
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Не может этого быть, у меня первый вариант это sar reg, 32.
     
  12. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Код (Text):
    1.     c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8));
    2. ...
    3. 1>.\test.cpp(10) : warning C4293: '>>' : shift count negative or too big, undefined behavior
    4. ...
    5. CPU Disasm
    6. Address   Hex dump          Command                                  Comments
    7. 00401019  |.  8B4424 14     MOV EAX,DWORD PTR SS:[ESP+14]
    8. 0040101D  |.  8B4C24 10     MOV ECX,DWORD PTR SS:[ESP+10]
    9. 00401021  |.  8BD1          MOV EDX,ECX
    10. 00401023  |.  2BD0          SUB EDX,EAX
    11. 00401025  |.  8BF0          MOV ESI,EAX
    12. 00401027  |.  2BF1          SUB ESI,ECX
    13. 00401029  |.  0BD6          OR EDX,ESI
    14. 0040102B  |.  C1FA 1F       SAR EDX,1F
    15. 0040102E  |.  23D0          AND EDX,EAX
     
  13. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Собиралось в MSVS 2005 SP1
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Не знаю, что у тебя со студией или с кодом. У меня 2005 и 2010 генерят сдвиг на 32. Странно если бы было иначе.

    Код (Text):
    1. #include <iostream>
    2.  
    3. int main (int argc, char* argv[])
    4. {
    5.     unsigned a = 3;
    6.     unsigned b = 1;
    7.     unsigned c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8));
    8.     std::cout << c << std::endl;
    9. }
     
  15. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Опа, оно в дебаге генерит:
    Код (Text):
    1. unsigned c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8));
    2. 004113CC  mov         eax,dword ptr [a]
    3. 004113CF  sub         eax,dword ptr [b]
    4. 004113D2  mov         ecx,dword ptr [b]
    5. 004113D5  sub         ecx,dword ptr [a]
    6. 004113D8  or          eax,ecx
    7. 004113DA  sar         eax,20h
    8. 004113DD  and         eax,dword ptr [a]
    9. 004113E0  mov         dword ptr [c],eax
    В релизе:
    Код (Text):
    1. 00401000  mov         eax,dword ptr [__imp_std::endl (402040h)]
    2. 00401005  mov         ecx,dword ptr [__imp_std::cout (402044h)]
    3. 0040100B  push        eax  
    4. 0040100C  push        3    
    5. 0040100E  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40203Ch)]
    2005 без SP. Ну вы поняли, это типа UB, нужно (sizeof(a)*8 - 1)).
     
  16. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Booster
    Код из #34 у меня так же компилируется как в посте #35.
    Дабы избежать подобных оптимизаций в релизе я тестировал на таком коде:
    Код (Text):
    1. #include "stdafx.h"
    2.  
    3. int _tmain(int argc, _TCHAR* argv[])
    4. {
    5.     unsigned a, b, c;
    6.     _tscanf(__T("%d %d"), &a, &b);
    7.     c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8));
    8.     _tprintf(__T(%d\n"), c);
    9.     return 0;
    10. }
    Тут получается сдвиг на 31, как ни странно.
     
  17. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Кстати, откуда дамп?
     
  18. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    google
    Как-бы намекает. ^)
    #36 у меня также даёт разные результаты.

    Из дизассемблера студии.
     
  19. skomarov

    skomarov New Member

    Публикаций:
    0
    Регистрация:
    14 май 2008
    Сообщения:
    389
    J0E
    Это по поводу моего решения? Вроде бы, во всем придерживался условий автора темы.
     
  20. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    skomarov
    ! это практически сравнение с нулём.