1. JavaScript / Говнокод #27392

    0

    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
    17. 17
    18. 18
    19. 19
    20. 20
    function test3()
    {
    		const a = 10.5
    	        switch (a) 
    		{                                            
    		    case 10.5:
            	        print("cool. 10.5");                          
    			break;                                          
    	        }
    }
    
    function test3()
    {		
    	        switch ("kokoko") 
    		{                                            
    		    case "kokoko":
            	        print("pituh");                          
    			break;                                          
    	        }
    }

    Продолжаем говнокомпилить...

    А ваш С такое прокомпилирует? мой - запросто :)

    Запостил: ASD_77, 05 Мая 2021

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

    • ну это ... асм дамп давать?
      Ответить
    • Твой язык с UB-ами или нет?
      Ответить
      • что такое UB? upper bound? unbound?
        Ответить
        • Undefined behaviour
          Ответить
          • у него весь код пока один большой UB :)
            Ответить
          • ну он то пишется на основе С стандартов поэтому все есть. нужно самому думать что делаешь ... и не допускать такие вещи как 1 << 32
            Ответить
    • А вот C++ — прокомпилирует!
      #include <iostream>
      #include <string_view>
      
      // FNV-1a
      constexpr uint64_t ct_hash(std::string_view str) noexcept
      {
          uint64_t val = 14695981039346656037ull;
          for (const auto & c : str) {
              val ^= static_cast<uint64_t>(c);
              val *= 1099511628211ull;
          }
          return val;
      }
      
      int main()
      {
          std::string hello = "world";
          
          switch(ct_hash(hello)) {
              case ct_hash("hello"): std::cout << "Case Hello!" << std::endl; break;
              case ct_hash("world"): std::cout << "Case World!" << std::endl; break;
          }
      }


      Причём оптимальным образом — сделает бинярный поиск по хэшам!
      Ответить
      • это хак коженного мешка а ни С ни С++ так как мой компилятор - не умеют :)
        Ответить
      • и кожанному мешку не обязательно писать свои хаки на hash. можно просто юзать std::hash по std::string :)
        Ответить
        • Няльзя. std::hash<> ня является constexpr, поэтому в компайлтайме вычислять метки по строкам им ня получится.
          Ответить
        • А у нас std::string constexpr на основных компиляторах разве?
          Ответить
          • std::string_view — constexpr. А вот std::hash<std::string_view>::operator() — ня constexpr。゚・ (>﹏<) ・゚。.
            Ответить
      • докажите что данный код будет работать для всех строк и пересечение хеша не произойдет
        Ответить
        • Компилятор докажет. А для исключения коллизий с входной строкой нядо в кейсы добавить сравнение, да. Плата за производительность!
          Ответить
          • А компилятор умеет генерировать оптимальные хеши без коллизий, если заранее известы все возможные вариации? Типа чтоб как https://www.gnu.org/software/gperf/

            https://neerc.ifmo.ru/wiki/index.php?title=Идеальное_хеширование
            Ответить
            • Такого даже в boost нет. Видимо крестопарашная метушня слишком убога для таких задач.
              Ответить
            • Там же алгоритм приведён. Перепиши его ня constexpr'ы и всё.
              Ответить
              • Там, я так подозреваю, нужны не только констэкспры, но и какая-то шаблоносрань. Констэкспрами ты код не сгенерируешь.
                Ответить
              • Вот реальный пример генерации
                https://git.savannah.gnu.org/gitweb/?p=gperf.git;a=blob;f=tests/test-4.exp;h=af0a2378e088228542636bce3274684a3ee69f94;hb=HEAD

                Одними констэспрами это не решить.
                Ответить
                • Разумеется, решить: https://wandbox.org/permlink/A2SBKuw91OCYKXl1 . Это, конячно, нямножко читерство (разбираться в математических дебрях лень), но задачу полностью выполняет.
                  Ответить
                  • https://godbolt.org/z/K4PrTsaz9 - да не, фигня какая-то.
                    Аллокаторы какие-то
                    call    func(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

                    Операторы delete какие-то
                    call    operator delete(void*, unsigned long)

                    В сгенерированном коде из
                    https://git.savannah.gnu.org/gitweb/?p=gperf.git;a=blob;f=tests/test-4.exp;h=af0a2378e088228542636bce3274684a3ee69f94;hb=HEAD
                    ничего этого нет. Ни единого выделения на хипе. Где ваше хваленое "zero-cost abstraction"?
                    Ответить
                    • Эта функция специальня сделана для демонстрации того, что Switcher способен хэшировать рантайм-строки. Измени сигнятуру на void func(std::string_view runtime_str) и радуйся.
                      Ответить
                      • А если я хочу в шаблон пропихнуть n-ное количество допустимых строк и того, что в ответ возвращать на такую-то строку, и чтоб там под них нагенерировалось столько-то switch-case - так можно?
                        Ответить
                        • Нячего ня поняла. Можня сделать
                          str = "good";
                          
                          Switcher<
                              Case<"Hello", "World">,
                              Case<"good", "bye">
                          >{}(str) == "bye"

                          , но тогда придётся бинярный поиск по хэшам вручную делать (в случае с обычным switch () {case} компилятор его сам делает).
                          Ответить
                          • > Нячего ня поняла.
                            #define H_abc 0
                            #define H_cde 1
                            #define H_efg 2
                            
                            char *somestring = "abc";
                            int result = perfect_hash<<"abc", H_abc>, <"cde", H_cde>, <"efg", H_efg>>(somestring);
                            // result == H_abc == 0

                            И чтоб из этого допустим switch-case код нагенерился, и количество пар ключ-значение произвольно.
                            Ответить
                            • Ня: https://wandbox.org/permlink/agzUP2JIbCSSzwOR . Тут как раз реализован имення квадратный двухступенчатый perfect hashing. Проверку ня коллизии и отсутствующие ключи оставляю в качестве домашнего задания (в lookup() сделать сравнение ключей). А, ну и у Case сделать шаблонный Value.
                              Ответить
                              • Да нет же!
                                void func(std::string_view str)
                                {
                                    auto switcher = Switcher<
                                        Case<"something", "world">,
                                        Case<"hmmm", "hello">,
                                        Case<"not", "used">
                                    >{};
                                
                                    std::puts(switcher(str).data());  // inb4: UB
                                }

                                Тут не генерируется никакого switch.
                                Давай так. Забудь вообще про perfect hash.
                                В коде https://wandbox.org/permlink/A2SBKuw91OCYKXl1 есть конструкция
                                .
                                    switch (switcher.hash(runtime_str)) {
                                    case switcher.hashkey<"hello">(): std::puts("Hello!"); break;
                                    case switcher.hashkey<"world">(): std::puts("World!"); break;
                                    case switcher.hashkey<"bye">(): std::puts("Bye!"); break;
                                    default: std::puts("No such string."); break;
                                    }

                                Вот я хочу просто сделать штуку, которая принимает через шаблонные параметры пары ключ-значение, и чтоб из этого в компилтайме генерировался код соотв. функции с такими-то свитчами. Я не хочу отдельно что-то описывать!

                                Где там конкретно конструкция switch - case в твоем примере?
                                Ответить
                                • Что-то я ня поняла, куда мы уехали. Изнячальня вопрос стоял так:
                                  > А компилятор умеет генерировать оптимальные хеши без коллизий, если заранее известы все возможные вариации?
                                  Ответ — да, умеет. Теперь это нядо посыпать сахаром?
                                  Ответить
                                  • > Ответ — да, умеет. Теперь это нядо посыпать сахаром?

                                    Ну так... если не посыпать сахаром, с этим отлично справится кодогенерация, и никакие супер-пупер фичи крестов не требуются.

                                    На констэкспрах, раз уж на то пошло, можно набросать собственный компилтайм-мини-компилятор который понабросает опкодов процессора куда-то, и потом это "куда-то" можно сделать в RX сегменте, кастануть в функцию и вызывать. Надо ли говорить, что такой подход не совсем адекватный?
                                    Ответить
                                    • Кодогенерация со всем отлично справится. Для таких штук оня, разумеется, гораздо более адекватный подход.
                                      Вопрос в другом: ты убедился, что constexpr-ушня может сгенерировать perfect hash?
                                      Ответить
                                      • То что хеш ей можно генерировать - я и не сомневался. А код она не генерирует.

                                        В крестах для генерации кода нужно шаблоноговно использовать, а это уже другая хуйня, которую констэкспрами не выразить.
                                        Ответить
                                        • Ну ладня, держи:
                                          template<typename... Cases>
                                          struct Switcher {
                                              constexpr Switcher(Cases...) {}
                                              constexpr static std::tuple<Cases...> cases{ Cases{}... };
                                          
                                              template<size_t I>
                                              constexpr static void execImpl(std::string_view key)
                                              {
                                                  constexpr auto & case_ = std::get<I>(cases);
                                                  if (case_.key == key) {
                                                      case_.func();
                                                      return;
                                                  }
                                                  
                                                  if constexpr (I < sizeof...(Cases) - 1) {
                                                      execImpl<I + 1>(key);
                                                  } else {
                                                      assert("No such key");
                                                  }
                                              }
                                          
                                              constexpr static void exec(std::string_view key)
                                              {
                                                  execImpl<0>(key);
                                              }
                                          
                                              constexpr void operator()(std::string_view key) const
                                              {
                                                  exec(key);
                                              }
                                          };
                                          
                                          void func(std::string_view key)
                                          {
                                              Switcher(
                                                  Case<"hello", [] { std::puts("Hello World"); }>(),
                                                  Case<"bye", [] { std::puts("Bye World"); }>(),
                                                  Case<"not used", [] { std::puts("123"); }>()
                                              )(key);
                                          }
                                          
                                          int main()
                                          {
                                              func("bye");
                                          }

                                          https://gcc.godbolt.org/z/droEe4Yrs

                                          Задачу прикручивания к этой фигне perfect hash'а и мутабельных лямбд оставляю ня тебя (*^‿^*)!
                                          Ответить
                                          • Кстати, забавня, что этот Switcher с линейным поиском gcc оптимизировал в великолепное:
                                            func(std::basic_string_view<char, std::char_traits<char> >):
                                                    cmp     rdi, 5
                                                    je      .L2
                                                    cmp     rdi, 3
                                                    je      .L19
                                                    cmp     rdi, 8
                                                    jne     .L20
                                                    movabs  rax, 7234315323333439342
                                                    cmp     QWORD PTR [rsi], rax
                                                    jne     .L1
                                                    mov     edi, OFFSET FLAT:.LC0
                                                    jmp     puts
                                            .L19:
                                                    cmp     WORD PTR [rsi], 31074
                                                    je      .L21
                                            .L1:
                                                    ret
                                            .L2:
                                                    cmp     DWORD PTR [rsi], 1819043176
                                                    jne     .L1
                                                    cmp     BYTE PTR [rsi+4], 111
                                                    jne     .L1
                                                    mov     edi, OFFSET FLAT:.LC2
                                                    jmp     puts
                                            .L21:
                                                    cmp     BYTE PTR [rsi+2], 101
                                                    jne     .L1
                                                    mov     edi, OFFSET FLAT:.LC1
                                                    jmp     puts
                                            .L20:
                                                    ret

                                            Что явня быстрее любых perfect hash'ей и бинярных поисков.
                                            Ответить
                                            • А это хоть чем-то кроме GCC вообще собирается?

                                              И там проблемы с оптимизацией заметны, компилятор почему-то делает jne .L20 на метку для инструкции ret в самом конце, хотя инструкция ret и так есть на метке .L1 которая идет после инструкции jmp puts который управление не вернет, так что кусок кода
                                              .L20:
                                                      ret

                                              нафиг не нужен. Переход на метку .L20 можно заменить на переход на метку .L1
                                              Ответить
                                              • > А это хоть чем-то кроме GCC вообще собирается?
                                                GCC и MSVC. Шланг ня может.

                                                > jne .L20
                                                Это всё равно холодный путь, так что никакого влияния ня перформанс ня окажет.
                                                Ответить
                                            • И да, руками можно это получше записать. Далеко не идеал.

                                              Кроме того, начиная с какого-то там количества вариантов, подход с таблицей поиска оказывается лучше хрени с условями. И фиг его знает, что там компилятор понакомпилириует
                                              Ответить
                                              • > Далеко не идеал.
                                                То ли дело сишка!
                                                void func(const char *key)
                                                {
                                                    if (strcmp(key, "hello") == 0) {
                                                        puts("Hello World");
                                                    } else if (strcmp(key, "bye") == 0) {
                                                        puts("Bye World");
                                                    } else if (strcmp(key, "not used") == 0) {
                                                        puts("123");
                                                    }
                                                }

                                                func:
                                                        push    rbp
                                                        mov     esi, OFFSET FLAT:.LC0
                                                        mov     rbp, rdi
                                                        call    strcmp
                                                        test    eax, eax
                                                        je      .L7
                                                        mov     esi, OFFSET FLAT:.LC2
                                                        mov     rdi, rbp
                                                        call    strcmp
                                                        test    eax, eax
                                                        je      .L8
                                                        mov     esi, OFFSET FLAT:.LC4
                                                        mov     rdi, rbp
                                                        call    strcmp
                                                        test    eax, eax
                                                        je      .L9
                                                        pop     rbp
                                                        ret
                                                .L8:
                                                        mov     edi, OFFSET FLAT:.LC3
                                                        pop     rbp
                                                        jmp     puts
                                                .L7:
                                                        mov     edi, OFFSET FLAT:.LC1
                                                        pop     rbp
                                                        jmp     puts
                                                .L9:
                                                        mov     edi, OFFSET FLAT:.LC5
                                                        pop     rbp
                                                        jmp     puts

                                                https://gcc.godbolt.org/z/qq8vxvbze
                                                Позорище!
                                                Ответить
                                                • > То ли дело сишка!

                                                  На сишке я вручную это запрограммирую(возможно даже в асмовставке), если оно окажется боттлнеком.
                                                  Ответить
                                                  • > На сишке я вручную это запрограммирую
                                                    Имення так. Вообще, сишники — это те же джависты, только вместо get set hashcode equals пишут вручную вообще всё: от управления ресурсами до исключений через setjmp.
                                                    Ответить
                                                    • > пишут вручную

                                                      И получается, чсх, быстрее и эффективнее, чем какая-то заумная крестометушня, которая работает не во всех компиляторах и требует последний стандарт.
                                                      Ответить
                                                      • > быстрее и эффективнее
                                                        [citation needed]

                                                        Пока что мы лишь увидели, как линейный поиск по заранее заданным строкам в крестах как тузик грелку порвал точня такой же линейный поиск по заранее заданным строкам в сишке.
                                                        Ответить
                                                        • > [citation needed]

                                                          https://wandbox.org/permlink/hrNq6pmrUutcxCt5 - примитивная кодогенерация.

                                                          https://gcc.godbolt.org/z/3a631c6Yx - результат.

                                                          Сравни это с https://gcc.godbolt.org/z/aa6Eqeze5 по качеству машинного кода.
                                                          Ответить
                                                          • Пока ты там писал примитивную кодогенерацию (ня забыл прописать её в Makefile?), которая ещё и сломается ня строках длиннее четырёх символов — крестовички просто пишут
                                                            switch(ct_hash(key)) {
                                                                    case ct_hash("hello"): std::puts("Case Hello!"); break;
                                                                    case ct_hash("world"): std::puts("Case World!"); break;
                                                                    case ct_hash("123"): std::puts("asdeger!"); break;
                                                                    case ct_hash("aa1"): std::puts("1!"); break;
                                                                    case ct_hash("aa2"): std::puts("2!"); break;
                                                                    case ct_hash("aa3"): std::puts("3!"); break;
                                                                    case ct_hash("aa4"): std::puts("4!"); break;
                                                                    case ct_hash("aa5"): std::puts("5!"); break;
                                                                    case ct_hash("aa6"): std::puts("6!"); break;
                                                                    case ct_hash("aa7"): std::puts("7!"); break;
                                                                    case ct_hash("aa8"): std::puts("8!"); break;
                                                                    case ct_hash("aa9"): std::puts("9!"); break;
                                                                    case ct_hash("aa10"): std::puts("10!"); break;
                                                                }

                                                            И сразу же получают оптимальный код.
                                                            https://gcc.godbolt.org
                                                            Ответить
                                                            • Оптимальный код этим не получится. На строках короче или равных 8 байт (64 бит) можно никакой хэш вообще не делать, а сравнивать через switch и это будет явно быстрее. Если строки длиннее 8 байт, и если первые 8 байт у них зачастую не совпадают, то всё равно можно сравнивать 8 байт через uint64_t и потом дальше уже допроверять остаток. Для оптимального кода нужны какие-то сложные эвристики, возможно даже есть смысл собрать статистику встречаемости таких-то строк и на основе этого заоптимизировать очередность сравнения. Так что до какой-то оптимальности тут очень далеко.
                                                              Ответить
                                                              • кстати если метки в switch-case идут плотно, т.е.
                                                                case 1: smth1(); break;
                                                                case 2: smth2(); break;
                                                                case 3: smth3(); break;
                                                                case 4: smth4(); break;

                                                                компилятор может сделать табличку поиска, т.е. попросту говоря массив из указателей на функции (или возможно на блоки кода), и в arr[1] будет присвоен указатель на функцию smth1(), в arr[2] будет присвоен указатель на функцию smth2() и так далее. И это будет быстрее хешей и бинарного поиска. Оптимизация хуиты в swich это вообще целая наука. Глупо надеяться на то, что можно сделать всё оптимально, используя какой-то там хэш
                                                                Ответить
                                                                • Если метки в свитчах помещаются в целое число данной архитектуры (ну там в 8 байт, например), то хеш наверное и вовсе никогда не нужен:)

                                                                  Но массив указателей это правда круто
                                                                  Ответить
                                                              • Зато соотношение скорости написания и простоты кода к его производительности у C++ вышло няилучшим. Пока сишник будет приделывать в свою билд-систему кодогенерацию ня HTML-шаблонах — крестовички няпишут десять таких свитчей. А если будет боттлнек — тогда уже можня переходить либо к Switcher (в который можня вкрутить любые эвристики), либо к, да, кодогенерации.
                                                                Ответить
                                                • >strcmp
                                                  ну так где свитч с бинароным поиском по хешу, а где 100500 strcmp
                                                  Ответить
                                                  • Какой бинярный поиск? Switcher с лямбдами — это просто тупой линейный перебор по кейсам со сравнением через ==. Собственно, потому на aaa-aaj он такую бредятину и сгенерировал: каждый cmp WORD PTR [rsi], 24929 — это ошмёток соответствующего execImpl<>().
                                                    Ответить
                                                    • Бинарный там или не бинарный поиск, какая мне разница? Тут ключ-значение. Пусть оптимально генерирует, раз там оно похоже по каким-то байтикам. Для таких случаев можно написать куда более эффективную реализацию.
                                                      Ответить
                                                      • Так почему же великая сишка даже ня трёх кейсах выдала позорные три вызова strcmp(), хотя код там одиняковый?
                                                        Ответить
                                                    • Я имел ввиду, что можно сделать супероптимальное говно (свитч по хешам, который затем компилятор превратит в бинарное дерево, если верить Мыщъу), а вы какой-то ужас показываете с серией strcmp

                                                      Можно, кстати, и не по хешам, а просто разбить слова на буковки, и сделать дерево по буковкам же
                                                      Ответить
                                                      • Супероптимальное говно — в https://wandbox.org/permlink/agzUP2JIbCSSzwOR, я там сделала компайл-тайм perfect hashing и лукап за два вычисления хэша от ключа — асимптотически это O(1), быстрее, чем бинярный поиск. Правда, для малого количества ключей оно някнет даже линейному поиску через сравнения, что мы тут и продемонстрировали.
                                                        Ответить
                                                        • напишити умный кот, который для малого кол-ва ключей будет делать линейный пошук по массиву, а для большого -- превращаться вхеш
                                                          Ответить
                                                          • Здесь представлены варианты Switcher и с хэшами, и с линейным поиском. Объедини их — и готово (¬‿¬ )!
                                                            Ответить
                                                      • > свитч по хешам, который затем компилятор превратит в бинарное дерево, если верить Мыщъу
                                                        У меня в реальном коде используется имення такой свитч. И да, компилятор действительня превращает его в бинярное дерево:
                                                        void func(std::string_view key)
                                                        {
                                                            switch(ct_hash(key)) {
                                                                case ct_hash("hello"): std::puts("Case Hello!"); break;
                                                                case ct_hash("world"): std::puts("Case World!"); break;
                                                                case ct_hash("123"): std::puts("asdeger!"); break;
                                                                case ct_hash("aa1"): std::puts("1!"); break;
                                                                case ct_hash("aa2"): std::puts("2!"); break;
                                                                case ct_hash("aa3"): std::puts("3!"); break;
                                                                case ct_hash("aa4"): std::puts("4!"); break;
                                                                case ct_hash("aa5"): std::puts("5!"); break;
                                                                case ct_hash("aa6"): std::puts("6!"); break;
                                                                case ct_hash("aa7"): std::puts("7!"); break;
                                                                case ct_hash("aa8"): std::puts("8!"); break;
                                                                case ct_hash("aa9"): std::puts("9!"); break;
                                                                case ct_hash("aa10"): std::puts("10!"); break;
                                                            }
                                                        }
                                                        ...
                                                        movabs  rcx, 620444549055354499
                                                                cmp     rax, rcx
                                                                je      .L4
                                                                movabs  rcx, -1793442995417202535
                                                                cmp     rdx, rcx
                                                                ja      .L5
                                                                movabs  rcx, 620444549055354496
                                                                cmp     rax, rcx
                                                                je      .L6
                                                                movabs  rcx, -1793446293952087168
                                                                cmp     rdx, rcx
                                                                jbe     .L22
                                                                movabs  rdx, 620444549055354497
                                                                cmp     rax, rdx
                                                                je      .L11
                                                                add     rdx, 1
                                                                cmp     rax, rdx
                                                                jne     .L23
                                                                mov     edi, OFFSET FLAT:.LC7
                                                                jmp     puts
                                                        ...

                                                        https://gcc.godbolt.org/z/9jzYYcvha

                                                        Проверки ня коллизии выкинуты для няглядности.
                                                        Ответить
                                            • При таких данных https://gcc.godbolt.org/z/aa6Eqeze5 результирующий код получается уже совсем неадекватным. А ведь всего-то надо понять, что первые две буковки у нас "aa" и потом проверить третью буковку.
                                              Ответить
                              • https://wasm.in/blogs/identifikacija-switch-case-break.106/ кстати рекомендую вот, по оптимизации поиска соответствия значениям из switch
                                https://wasm.in/archive/pub/9/pic/p33.gif

                                Если крестовым говнометапрограммированием нельзя просто понабрасывать меток case в этот switch и дать компилятору делать свое дело, нужно как-то ручками нагенерировать кучу if() хреней оптимальным образом (занимаясь работой компилятора).
                                Ответить
                                • Охуенная мысль руками построить двоичное дерево из ифоф, чтобы искать нужную ветку в свитче не за N, воу

                                  Нет уж, лучше руками написать свитч, и пусть ебется компилятор, ведь он умел это еще в 2002-м году.

                                  Интересно другое: один свитч на 20 веточек получается оптимальнее, чем 20 ифэлсов.
                                  Ответить
                                  • > один свитч на 20 веточек получается оптимальнее, чем 20 ифэлсов

                                    Потому что одна ошибка предсказания дешевле чем пять, лол.
                                    Ответить
                                    • да)

                                      Но замечание Криса в том, что если ты заранее знаешь все возможные варианты, то ты просто ложишь их в двоичное дерево, и потом можешь по ним скакать за логорифм.

                                      Можно кстати посчитать от них хеши, и сделать хетаблицу.
                                      Ответить
                                  • > Интересно другое: один свитч на 20 веточек получается оптимальнее, чем 20 ифэлсов.

                                    Иногда компиляторы могут 20 ифелсоф распознать как switch и заоптимизировать его по аналогичной схеме.
                                    Ответить
                                • > https://wasm.in/archive/pub/9/pic/p33.gif
                                  Это нязывается "бинарный поиск".
                                  Ответить
                                  • Есть еще ньюанс. После x86 инструкции "cmp" мы можем сразу понять по флагам, больше, меньше или равно. Получается троичное дерево.


                                    https://konyakov.ru/pubs/books/kris-kaspersky-r_i_p/kris-kaspersky-27.pdf
                                    > Балансировка логического дерева

                                    > Учитывая, что x86 процессоры все три операции сравнения <, =, > совмещают в одной машинной команде, двоичное логическое дерево можно преобразовать в троичное,тогда новых гнезд для его балансировки добавлять не нужно. Простейший алгоритм, называемый методом отрезков,работает так: сортируем все числа по возрастанию и делимполучившийся отрезок пополам. Число, находящееся по-середине (в нашем случае это 11), объявляем вершинойдерева, а числа, расположенные слева от него, – его левы-ми ветвями и подветвями (в нашем случае это 0, 3, 4 и 7).Остальные числа (22, 96, 98, 666, 777) идут направо.
                                    Ответить
                                    • Ну вот только бранча сразу на 3 стороны у "x86" нету. И вместо относительно дешёвого сравнения с константой мы получим по джва условных перехода на каждом уровне дерева.

                                      Х.з., это точно хороший хак? Пруфы пирфоманса есть?
                                      Ответить
                                      • > Х.з., это точно хороший хак? Пруфы пирфоманса есть?

                                        Я думаю что это от процессора зависит сильно. Ну вообще можно побенчмаркать конечно.

                                        Если какой-то 8-битный говноконтроллер без префетчей, там вполне норм будет
                                        cmp(reg0, reg1)
                                        goto_if_gr l1
                                        goto_if_ls l2
                                        
                                        ##а тут код, который выполняется если reg0 == reg1
                                        
                                        goto end
                                        
                                        l1:
                                        ##тут код, который выполняется если reg0 > reg1
                                        goto end
                                        
                                        l2:
                                        ##тут код, который выполняется если reg0 < reg1
                                        
                                        end:
                                        Ответить
      • насколько я помню switch это не код а асм команда. там нет поиска по бинарнику.
        Ответить
        • Нет, компилятор умеет разворачивать switch() в бинярный поиск при няличии достаточного количества кейсов: https://godbolt.org/z/3fEej91nj . А вот если кейсы лежат достаточня близко друг к другу, тогда компилятор генерирует простую проверку границ и прыжок по таблице.
          Ответить
      • если это constexpr то чому enumы не сделать?
        Ответить
        • По условиям задачи строка, по которой нядо сделать switch, приходит к ням в рантайме — из std::cin, няпример.
          Ответить
          • но тогда может совпать хеш
            о, бля, у вам там целый тредик про это
            изхвини
            Ответить
            • Для этого после каждого case нядо делать рантайм-сравнение строки с ключом.
              Ответить
              • ну да, совпадение хеша бывает раз в стол лет, можно и сравнить

                вообще свищ по строкам -- штука не однозначная, в реальном мире у нее мало полезных кейсов (кроме разве что literal types в TS) и скриптушне

                интересно, на кой черт ее завезли в джавы и C#?
                Ответить
                • не поверишь - такое случается сплош и рядом особенно со словами в uppercase
                  Ответить
                  • Используй нярмальный 64-битный хэш, которому на uppercase глубоко няплевать.
                    Ответить
                  • напомнило


                    LM-хеш вычисляется следующим образом:

                    * Пароль пользователя приводится к верхнему регистру.
                    * Пароль дополняется нулями или обрезается до 14 байтов.
                    * Получившийся пароль разделяется на две части по 7 байтов.
                    * Эти значения используются для создания двух ключей DES, по одному для каждой 7-байтовой половинки, при этом 7 байтов рассматриваются как битовый поток и после каждых 7 битов вставляется ноль. Так создаются 64 бита, необходимые для ключа DES.
                    * Каждый из этих ключей используется для DES-шифрования ASCII-строки «[email protected]#$%», в результате получаются два 8-байтовых шифрованных значения.
                    * Данные шифрованные значения соединяются в 16-байтовое значение, являющееся LM-хешем.
                    Ответить
                    • > или обрезается до 14 байтов

                      Как вообще можно было додуматься обрезать пароли? Почему бы честно не сказать юзеру, что его пароль слишком длинный?
                      Ответить
                      • А в верхний регистр переводить?

                        В 1993-м году о безопасности даже в большом Интернете не думали (finger в inetd наружу торчал), а уж в опенспейсовых кубиках офисов и подавно.
                        Ответить
    • Какой паттерн-матчинг :). А по значением нескольких полей объектов сопоставлять умеет?
      Ответить
      • не знаю по каким полям но вот так легко делает
        function test5()
        {
        		let a = 10;
        		let b = 20;
        	        switch (30) 
        		{                                            
        		    case a + b: {
                	        print("cool. working.");                          
        			break;
        		   }                                          
        	        }
        }
        Ответить

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