1. C++ / Говнокод #18815

    +9

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    int turn = m_mapObject->getTurnSpeed();
    //НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
    if (turn != 0) {
        if (turn > 0) {
        //                    qDebug() << "Turn plus";
            turn /= 45;
            if (turn < 4) turn = 4;
            if (turn > 8) turn = 8;
        } else {
        //                    qDebug() << "Turn minus";
            turn /= 45;
            if (turn > -4) turn = -4;
            if (turn < -8) turn = -8;
        }
        paint.drawLine(QPoint(0,-speed),QPoint(turn,-speed));
    }

    Вы б знали, как руки чешутся...

    Запостил: Antervis, 05 Октября 2015

    Комментарии (36) RSS

    • На что только не пойдёт байтоёб чтоб сделать за компилятор его работу.
      Ответить
      • нет такого преступления, на которое бы не пошёл байтоёб ради прироста в 2%
        Ответить
        • Обеспечьте байтоёбу 1% прироста, и байтоёб согласен на всякое применение, при 2% он становится оживлённым, при 3% положительно готов сломать себе голову, при 5% он попирает все человеческие законы, при 10% нет такого преступления, на которое он не рискнул бы пойти, хотя бы под страхом некорректной работы программы.
          Ответить
        • > нет такого преступления, на которое бы не пошёл байтоёб ради прироста в 2%
          int turn = m_mapObject->getTurnSpeed();
          // > НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
          // А ПОЧЕМУ БЫ И НЕТ?
          if (turn != 0) {
              int s=turn>>31,a=turn+s^s,b=(a>360?524288:a>180?a*1457:262144)>>16;
              turn=b+s^s;
              paint.drawLine(QPoint(0,-speed),QPoint(turn,-speed));
          }
          Пруф: http://ideone.com/E7ZqWG
          Ответить
          • Добиваем последние условные операторы и мозг читателя:
            int turn = m_mapObject->getTurnSpeed();
            // > НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
            // А ПОЧЕМУ БЫ И НЕТ?
            if (turn != 0) {
                int s=turn>>31,a=turn+s^s,m=a-180>>31,n=a-360>>31,b=262144&m|a*1457&~m&n|524288&~n;
                turn=(b>>16)+s^s;
                paint.drawLine(QPoint(0,-speed),QPoint(turn,-speed));
            }
            Юнит-тест: http://ideone.com/BNHV8p

            bormand кончил и закурил.
            Ответить
            • Финальная версия:
              int turn = m_mapObject->getTurnSpeed();
              // > НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
              // А ПОЧЕМУ БЫ И НЕТ?
              if (turn != 0) {
                  int s=turn>>31,a=turn+s^s;
                  turn = (a-360>>31&(180-a>>31&(1457*a>>16^4)^12)^8)+s^s;
                  paint.drawLine(QPoint(0,-speed),QPoint(turn,-speed));
              }
              Юнит-тест: http://ideone.com/nTKaLF
              Ответить
              • Кстати, прикольный эффект от branch predictor'а - если числа этой функции по порядку скармливать, то мой код работает на 34% медленней оригинала. Но если функцию кормить рандомными числами - на 40% быстрее.
                Ответить
                • Сорри, оптимизацию забыл включить. С -O2 мой код выигрывает 2% при последовательном обходе и 40% при рандомном.
                  Ответить
                  • А с ключом -O3 даст три процента?
                    Ответить
                    • Бля, я понял, разрабы не дают компилякать с -O101, чтобы время не пошло в обратную сторону и не пришлось снова просить Кармака вернуть как было.
                      Кстати, его 10-летний сын написал свою вторую игру, 2k строк на диалекте лиспа.
                      http://1k3c.com
                      К чему это я? Пойду в своё колесо, свернусь комочком и порыдаю над своими тупостью и ленью.
                      Ответить
                      • // НЕ НАДО ТУТ КОНПЕЛИРОВАТЬ С -O101 !!!!
                        Ответить
                      • > чтобы время не пошло в обратную сторону

                        Jeff Dean was forced to invent asynchronous APIs one day when he optimized a function so that it returned before it was invoked.
                        Ответить
              • А объяснить для глупых можно? :(
                Ответить
                • Используется сакральное знание о машинном представлении чисел с плавающей точкой. Дальше дело побитовой магии.
                  Ответить
                • s - знак числа. Когда мы двигаем знаковое число вправо, дырки с левой стороны заполняются знаковым битом. И если мы сдвинем int32_t на 31 бит вправо, мы получим 0xFFFFFFFF (-1) если там был минус и 0x00000000 если плюс или ноль.

                  a = abs(turn). Здесь код читается не совсем так, как кажется на первый взгляд - (turn+s)^s, у плюса приоритет больше. При s=0 получается (turn+0)^0 -> turn, при s=-1 получается (turn-1)^(-1) -> ~(turn-1) -> -turn (в процах, емнип, neg через побитовый not так и запилен).

                  To be continued...
                  Ответить
                • (a-360)>>31 - тот же приём, что и в s, здесь мы определяем знак числа a-360. Т.е. если a>=360, мы получаем 0, а если a<360 - получаем 0xFFFFFFFF.

                  (180-a)>>31 - аналогично, если a>180 - 0xFFFFFFFF, иначе 0

                  Эти значения далее будут использоваться как маски, чтобы реализовать подобие тернарника.

                  To be continued...
                  Ответить
                • (1457*a)>>16 - классическое умножение делением. Нам надо поделить на 45, т.е. умножить на 1/45. Подберём ближайшую дробь со знаменателем кратным степени двойки 1/45 ~ 1457/65536. Т.е. чтобы поделить на 45 мы можем умножить на 1457 и поделить на 65536. Деление на 65536 - обычный сдвиг на 16 вправо, ради этого такой красивый знаменатель и выбирался.

                  To be continued...
                  Ответить
                • Дальше идут "тернарники". Суть идеи в выражении (mask & (a^b)) ^ a. При mask == 0 получаем a, а при mask == 0xFFFFFFF получаем a^b^a, т.е. b. Там два таких тернарника.

                  По сути там a > 360 ? 8 : a > 180 ? a / 45 : 4.

                  Ну и последнее +s^s восстанавливает знак числа. Вот и всё байтоёбство, ничего особо сложного :)
                  Ответить
              • Ты забыл __asm заюзать
                Ответить
                • Сложный вопрос. Тогда пришлось бы читать том по микрооптимизации. А гцц и сам неплохо раскидывает команды под выбранную архитектуру, поэтому я не стал заморачиваться.
                  Ответить
      • дело ж не в байтоебстве совсем, а в оформлении кода
        Ответить
      • Байтоёб как минимум вставил бы else, чтобы устранить лишние проверки, а также вынес бы turn /= 45.
        Ответить
        • > вынес бы turn /= 45
          //НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
          Ответить
    • А я возьму и оптимизирую что-нибудь!
      int turn = m_mapObject->getTurnSpeed();
      //НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
      if (turn != 0) {
              int abs_turn = abs(turn);
              int sign_turn = (turn > 0) ? 1 : -1;
              turn /= 45;
              if (abs_turn > 8) turn = 8 * sign_turn;
              else if (abs_turn < 4) turn = 4 * sign_turn;
      
          // if (turn > 0) {
          //                    qDebug() << "Turn plus";
          // } else {
          //                    qDebug() << "Turn minus";
         // }
      
          paint.drawLine(QPoint(0,-speed),QPoint(turn,-speed));
      }
      Ответить
    • //ВОТ ТУТ ТОЧНО НЕ НАДО ТУТ ОПТИМИЗИРОВАТЬ /= 45 !!!!
      if (turn != 0) {
        switch (turn) {
          case 1: turn /= 45;
          case 3: turn /= 45;
          case 8: turn /= 45;
          default:
            // qDebug() << "Turn-45";
        }
      }
      Ответить
    • супер))))
      Ответить
    • Гейдев?
      Ответить

    Добавить комментарий