1. Си / Говнокод #11324

    +135

    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
    float Q_rsqrt( float number )
    {
            long i;
            float x2, y;
            const float threehalfs = 1.5F;
     
            x2 = number * 0.5F;
            y  = number;
            i  = * ( long * ) &y;                       // evil floating point bit level hacking
            i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
            y  = * ( float * ) &i;
            y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
    //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
    
            return y;
    }

    The following code is the fast inverse square root implementation from Quake III Arena, stripped of C preprocessor directives, but including the exact original comment text.

    Вот что такое настоящие магические числа.

    Запостил: bormand, 30 Июня 2012

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

    • 0x5f3759df — похоже что верхняя граница.
      Мини ГСЧ?
      Ответить
      • > Мини ГСЧ?
        Нет, не угадали ;) Сдвиг флоата на бит вправо и вычитание из этого магического числа возвращает достаточно хорошее приближение 1.0/sqrt(number).
        Ответить
        • >Нет, не угадали
          //fixed
          Обфейлился.

          Как-то писал мини ГСЧ и в качестве смещения использовал адреса переменных с последовательным приведением к разным типам и произвольным сдвигом(тудой-сюдой) — напомнило, но не оно.
          Ответить
          • Хм, а чем не подходили классические ГПСЧ типа a = (a*b+с) mod m, если не секрет?
            Ответить
            • Суть такова:
              Экзотики, экзотики...и зазудело в одном месте(руки).
              Идиты на хрен со своей экзотикой! - сказал, уже после, рассудок.
              Ответить
        • Впервые про быстрый обратный корень я узнал, читая инфу по квейку.
          Ответить
    • Было уже.
      И не один раз вроде.
      Ответить
      • Не помню. Недавно было крутое деление floatов на степени двойки, это да.
        /r prooflink
        Ответить
      • Поиск по 0x5f3759df показывает только эту страничку. Может просто похожий код был?
        Ответить
        • Да вот именно из кваки третьей. В любом случае, довольно старый хак.
          http://en.wikipedia.org/wiki/Fast_inverse_square_root вот тут, кстати, расписан весь матан.
          Ответить
          • Именно с вики я и скопипастил этот код (и комментарий под ним).

            Просто сегодня попался вот этот комикс http://xkcd.ru/664/. И я заинтересовался тем, что это за алгоритм, и почему именно 0x5f375a86. Вот после раскуривания статьи на вики, я и решил выложить код сюда...
            Ответить
          • Про Кармака это конечно известно - баян, да. Но ведь на гкоде не было ни разу.
            Кстати там прикол в том что несколькими годами ранее амд выпустила 3dnow и туды была впилена специальная инструкция для быстрого isqrt.
            И вообще изобрел это не Кармак, но известность метод получил именно благодаря ему.
            Ответить
    • > const float threehalfs = 1.5F;
      > 0x5f3759df
      у автора определённо есть чувство юмора
      Ответить
      • const unsigned int onebillionfivehundredninetysevenmillionf ourhundredsixtythreethousandseven = 0x5f3759df;
        Ответить
      • Только сейчас заметил что там threehalfs. До этого читал как threefalls, и не мог понять при чем тут три водопада?
        Ответить
    • показать все, что скрытоХорошо ещё, что это не формочка со случайно расположенными 20 кнопками и полями с именами Button1-20, где вся логика программы описана в обработчиках событий.

      Да и всю работу делает компонент TResolveProblem.

      Так что дельфисты покруче вещи выдают.
      Ответить
      • вообще не в кассу
        Ответить
      • Fai, вам на гк выше. #11325
        Ответить
        • Кстати да, ищу ищу свой коммент выше и о боже...
          Ответить
      • > вся логика программы описана в обработчиках событий
        > всю работу делает компонент TResolveProblem
        Путаемся в показаниях?
        Ответить
        • в обработчиках просто стоит код вида TResolveProblem1->resolve()
          Интересно какой "гений" придумал делать компоненты даже для сокетов?
          Ответить
          • > в обработчиках просто стоит код вида TResolveProblem1->resolve()
            Ну так это же труъ ООП! В обработчиках минимум кода, а всю логику содержит класс, посвященный определенной задаче. Другое дело что на делфи редко кто так пишет - в типичной проге все свалено в обработчики. И свои компоненты типичный дельфин писать не умеет...

            > компоненты даже для сокетов
            Имхо это сделано для новичков - не надо думать как описать переменную, как создать объект, как установить свойства и т.п. Кинул - и работает. С другой стороны мне кажется, что невизуальным компонентам на форме не место. Лучше сделали бы специальное окошко под них (в визуал студии вроде так и есть). И опять же все эти упрощения для новичков приводят к тому, что они так и не понимают, что же тут происходит, и используют систему как черный ящик...
            Ответить
            • > Другое дело что на делфи редко кто так пишет - в типичной проге все свалено в обработчики

              И правильно сделано.
              VCL и так отделяет код гуя (вся байда с HWND) от кода логики (класс TForm1), но рахитекторам и этого мало.
              Даже если Ымбаркадеро в новой версии сделает так, что все обработчики по умолчанию будут содержать одну строчку DoSmth с созданием этого DoSmth в отдельно модуле, то рахитекторы будут смеяться над теми, кто пишет логику прямо внутри DoSmth, типа это смешение логики и гуя.
              Ответить
              • Одно дело когда в обработчике кнопки написано сделать то-то и то-то. Этот код вполне нормален.

                Другое дело, когда в обработчиках отрисовки гридов начинают запиливать раскрашивание ячеек и т.п, или в обработчиках onChar и прочего начинают клепать фильтрацию ввода, вместо того, чтобы породить свой компонент от стандартного, и загнать в него этот функционал.
                Ответить
                • А вот тут согласен. Нефиг форме отсылать работу с внутренней логикой компонента.
                  Ответить
              • Продолжим...

                Вторая проблема сваливания всего в обработчики - переусложнение. Типичный дельфин пытается упихать всю логику в обработчик. Не зная (или, порой, не желая знать) о том, что можно запилить приватный метод с осмысленным названием и вынести в него часть кода, особенно повторяющегося.
                Ответить
                • Не кажутся ли вам рассуждения о типичном дельфине несколько бессмысленными, ну или просто не достойными внимания. (Я сам с типичным дельфином не знаком, может он труъ чувак, и поговорить о нём стоит...)
                  Ответить
                  • Типичный дельфин это как средняя температура по больнице ;)
                    Я просто описываю общие тенденции в коде на делфи, с которым мне приходилось столкнуться.
                    Ответить
              • Третья проблема - это, как не странно, смешение логики и гуя (подожди Тарас, не говори что я хуй, пока не дочитаешь до конца).

                К примеру мы разрабатываем простейший чат. Самое простое, что приходит в голову - кинуть на форму сокет, навешать обработчиков на его сигналы, и в них запилить разбор пакетов и прочее. Так и поступит типичный дельфин. А здесь, как раз, стоило бы вынести реализацию протокола в другой класс\компонент. И из гуевых обработчиков уже дергать его достаточно высокоуровневые методы...
                Ответить
            • > специальное окошко под них (в визуал студии вроде так и есть)
              В студии (по крайней мере в версиях 2008+ вплоть до current) так и есть, но это не отдельное окошко, а панель такая. И она неразрывно связана с вкладкой, на которой ты делаешь визуальное проектирование. Увидеть их раздельно невозможно. Так что логическая прямая связь между формой и этими самыми невизуальными компонентами прослеживается и в студии.
              Ответить
              • Но по крайней мере эти компоненты не валяются среди кнопок и инпутбоксов ;)
                Ответить
              • >Так что логическая прямая связь между формой и этими самыми невизуальными компонентами прослеживается и в студии.

                ЕМНИП, связь прослеживается в винде, т.к. все сообщения привязаны к окнам
                Ответить
          • В делфи? Так легче писать приложения.
            Ответить
      • Вы правы, этот код наглядно показывает основные недостатки применения Хаскелла для программирования распределённых баз данных.
        Ответить
      • Вот ведь оно как бывает - говнокодом ошибся, а результат такой же.
        Ответить
    • Кармак - сынок.
      #define OD_RSQRT_INSHIFT 16
       #define OD_RSQRT_OUTSHIFT 14
      
      +    Error is always within +/1 of round(1/sqrt(t))*/
       static int32_t od_rsqrt_norm(int32_t t)
       {
      -   return (int32_t)floor(.5 +
      -    (1 << OD_RSQRT_OUTSHIFT)*(1.0/sqrt(t/(double)(1 << OD_RSQRT_INSHIFT))));
      +  int16_t n;
      +  int32_t r;
      +  int32_t r2;
      +  int32_t ry;
      +  int32_t y;
      +  /* Range of n is [-16384,32767] ([-0.5,1) in Q15).*/
      +  n = t - 32768;
      +  /*Get a rough initial guess for the root.
      +    The optimal minimax quadratic approximation (using relative error) is
      +     r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485).
      +    Coefficients here, and the final result r, are Q14.*/
      +  r = (23565 + OD_MULT16_16_Q15(n, (-13481 + OD_MULT16_16_Q15(n, 6711))));
      +  /*We want y = t*r*r-1 in Q15, but t is 32-bit Q16 and r is Q14.
      +    We can compute the result from n and r using Q15 multiplies with some
      +     adjustment, carefully done to avoid overflow.*/
      +  r2 = r*r;
      +  y = (((r2 >> 15)*n + r2) >> 12) - 131077;
      +  ry = r*y;
      +  /*Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5).
      +    This yields the Q14 reciprocal square root of the Q16 t, with a maximum
      +     relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a peak
      +     absolute error of 2.26591/16384.*/
      +  return r + ((((ry >> 16)*(3*y) >> 3) - ry) >> 18);
       }
      
      # define OD_MULT16_16_Q15(a,b) \
       151   (((int16_t)(a)*((int32_t)(int16_t)(b))) >> 15)
      Ответить

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