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

    +2

    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
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    // https://github.com/Samsung/ADBI/blob/3e424c45386b0a36c57211da819021cb1929775a/idk/include/division.h#L138
    
    /* Long division by 10. */
    static unsigned long long int div10l(unsigned long long int v) {
    
        /* It's a kind of magic.  We achieve 64-bit (long) division by dividing the two 32-bit halfs of the number 64-bit
         * number.  The first (most significant) half can produce a rest when dividing, which has to be carried over to the
         * second half.  The rest_add table contains values added to the second half after dividing depending on the rest
         * from the first division.  This allows evaluation of a result which is almost correct -- it can be either the
         * expected result, or the expected result plus one.  The error can be easily detected and corrected.
         */
        
        /* one dream */
        static unsigned long long int rest_add[] = {
            0x00000000, 0x1999999a, 0x33333334, 0x4ccccccd, 0x66666667,
            0x80000001, 0x9999999a, 0xb3333334, 0xcccccccd, 0xe6666667
        };
        
        /* one soul */
        unsigned long long int a = div10((unsigned int)(v >> 32));
        unsigned long long int b = div10((unsigned int)(v & 0xffffffff));
        
        /* one prize */
        int ri = (v >> 32) - a * 10;
        
        /* one goal */
        unsigned long long int ret = (a << 32) + b + rest_add[ri];
        
        /* one golden glance */
        if (ret * 10L > v) {
            //printf("OGG %llu %llu\n", ret * 10, v);
            --ret;
        }
        
        /* of what should be */
        return ret;
    }

    Деление на 10. Но зачем? Неужели компилятор настолько туп, что сам не может этого сделать?
    И да, эти туповатые комментарии one dream, one soul это отсылка к песне Queen - A Kind of Magic https://youtu.be/0p_1QSUsbsM

    Запостил: j123123, 03 Марта 2018

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

    • нухясе битоёбство в 2018
      Ответить
      • Это даже не битоёбство толком.
        Просто разбили 64-битное деление на 2 32-битных.
        >a = div10((unsigned int)(v >> 32));
        >b = div10((unsigned int)(v & 0xffffffff));

        Дистрибутивность для пятиклассников.
        (hi+lo)/10 = hi/10+lo/10;

        Вот интересенее div10 посмотреть. Там наверняка умножение на "магию".
        Ответить
    • Хуева туча кода, и это должно быть быстрее, чем деление на 10?
      Ответить
      • Походу это особое деление на 10 для uint64_t для процессоров, в которых 64-битных регистров тупо нет. Т.е. тупо нет инструкции "поделить какое-то 64-битное число на что-то" и приходится извращаться подобным образром. https://godbolt.org/g/4WCQse - вон компилятор GCC тоже какой-то __udivdi3 вызывает, если с флагом -m32 надо делить 64-битный unsigned int на 10. Это все в libgcc должно быть, и у clang тоже должна быть подобная хрень.

        И да этот __udivdi3 является более общим случаем(т.е. делить можно не только на 10, а на любую фигню), а в этом говнокоде особая заточенная реализация для деления именно на 10
        Ответить
        • Давай, давай, а ну, давай,
          Меня шмонай ты, вертухай,
          Да загляни под юбочку,
          Да посмотри на булочки.
          Понюхай попку носиком,
          Прикинься, киса, пёсиком,
          Вот в этом вся и разница,
          Кто хочет, а кто дразнится.

          ©Любимая группа мамки админа
          Ответить
        • >ARM processors don't have hardware support for division.

          Там деления вообще нет.
          Но тут дело в том что gcc/clang давным-давно научились вычислять "магические числа" при компиляции, и заменять деление на умножение + сдвиг.

          Даже жабовский hotspot лет 5 назад научился оптимизировать деление на константы. Потому непонятно зачем писать весь этот код.
          Ответить
        • Я пишу: int div10(int num) { return num /10; }

          https://godbolt.org/g/ddmtnj
          Получаю imul (безо всяких флагов O2,O3):
          div10(int):
            mov eax, edi
            mov edx, 1717986919 // 0x66666667
            sar edi, 31
            imul edx
            sar edx, 2
            mov eax, edx
            sub eax, edi
            ret

          "Умный" код с гитхаба.
          static __attribute__((naked)) unsigned int div10(unsigned int v) {
              /* Instead of dividing by 10, we multiply the dividend by (0.1 * 2 ^ (32 + 3)).  The result will be 64-bit wide.
               * The first 32-bits of the result will be the quotient multiplied by (2 ^ 3).  Shifting this value right by 3 bits
               * will give us the final quotient.
               */
              __asm("ldr   r1, =0xcccccccd    \n"
                    "umull r1, r0, r1, r0     \n"
                    "lsr   r0, #3             \n"
                    "bx lr                    \n");
          }


          0x66666667*2 = 0xccccccce
          Ответить
          • А ну понятно. Они не хотят тянуть libgcc и всю обвязку.
            Тогда нормально.

            > Normally, the GCC compiler handles this problem.
            > Whenever a division operation is required, GCC inserts a call to a function, which replaces the division operation. This and other helper functions are implemented in libgcc, a library (usually static) distributed together with GCC. The compiler and linker take care about linking with this file automatically.

            >This library should even be included in the library when linking with the -nostdlib and similar switches. (However, this depends on the configuration.)

            >The libgcc library has its own dependencies as well, which we can not supply. For this reason, we need our own division algorithms.
            Ответить
            • То есть компилятор полагается на Link-time optimization?
              Ответить
              • Просто на наличие определенных функций.

                Джава вон про целый СтроительСтрок знает когда плюсик конпелит...
                Ответить
                • Кстати, кмк запороли простоту языка глупым исключением из своего же правила: не делать перегрузку операторов.

                  Использование "+" для конкатенации уже обсуждали. Уж лучше бы оставили конкатенацию м-м-максимально неудобной, а развивали либу, в тех местах где плюсики помогали быстро говнячить: sql, html, логгирование, формат-стринги.

                  Глядишь и говна меньше было бы: меньше бы клеили sqlи, а больше юзали prepared statement.

                  Меньше бы лепили тормозное логирование,
                  if (log.debugEnabled()){
                      log.debug("Hui: "+a+" pizda:"+b+" dzhigurga:"+c).
                  }

                  А больше юзали форматтеры:
                  log.debug("Hui: {} pizda:{} dzhigurga:{}",a,b,c).

                  Итд.
                  Ответить
                  • В джаве вообще очень много идиотизмов. Я не знаю по какой бараньей причине они не могут в датаклассы, в гереацию аксесоров/мутаторов, и в вывод типов

                    Перегрузка туда же относится.
                    Всё потому что 25 лет назад кто-то сказал "кококок, перегрузка усложняет код"
                    Ответить
                    • > и в вывод типов
                      Есть, причём довольно приличный. Лучше чем в C#.

                      > в генерецию аксесоров/мутаторов
                      import lombok.Getter; 
                      
                      @Getter @Setter private int pituh;



                      >датаклассы
                      import lombok.Data; 
                      @Data public class DataClass {
                      //дохуя полей
                      }

                      Ответить
                      • Довольно очевидно что речь шла о стандартной либе, а не об очередной аоп магии


                        Вывода типов нет. Напиши мне дефиницию переменной типа стринг, и сам увидишь
                        Ответить
                        • >а не об очередной аоп магии

                          Это не очередная аоп-магия. К аоп вообще никакого отношения.
                          Это часть языка. Подключаешь обычный jar (пару строк в мавене) и готово!

                          @Getter @Setter превращаются генерециями в обычные методы.
                          Ответить
                          • Ну прокси магия, какая разница если она не в стандартной либе?

                            Зы
                            Генереции это такие вореции?
                            Ответить
                            • И не прокси тоже.
                              В стандартной либе сделаны кодогенереции javax.annotation.processing.Processor

                              Они позволяют расширять язык такими штуковинами. Без изменения формата байт-кода и самого языка.

                              >Напиши мне дефиницию переменной типа стринг, и сам увидишь

                              String s="haha";
                              Ответить
                              • В момент копеляции? Уже лучше, но все равно датаклассов нет в либе, а в котлине и сишарпе есть
                                Ответить
                                • >а в котлине

                                  Фу, тот же jvm.
                                  Уж лучше в чистую яву аннотации добавлять, чем весь проект переписывать.

                                  Да и профита там особо нет. Уж лучше на скалу пересесть, если ява не нравится.
                                  Ответить
                                  • Так сахар же, ну сравни

                                    data class Foo(name:String)
                                    val foo = Foo("ddd")
                                    print(foo.name)
                                    Ответить
                                    • Ты так говоришь будто сахар это что-то хорошее.

                                      А с lombok это по-прежнему обычная ява, я в любой момент могу обратно сгенерить бойлеплейтный java-код, распидорасив аннотации.

                                      import lombok.*;
                                      PrintStream o=System.out;
                                      
                                      @Builder @Data
                                      class Foo{
                                          String name;
                                      }
                                      
                                      val foo=new Foo("ddd");
                                      o.print (foo.getName())
                                      Ответить
                                      • А что плохого в сахаре? Котлин интероперейтится с джавой, это же те же опкоды под jvm
                                        Ответить
                              • Ну и где вывод?

                                Вот вывод

                                var foo=12
                                val k = arrayOf(12,222)
                                Ответить
                                • val? Это автовывод?

                                  Кмк эта говнофича обычно только убивает читабельность кода.

                                  Ну если сильно хочется, то можно.
                                  >val k = arrayOf(12,222)
                                  import lombok.val;
                                  val x= Arrays.asList(1,3,4);


                                  Тем более фича неконсистентна return type в методе не выводит. Толк?
                                  Ответить
                                  • Выводит

                                    fun foo()=123

                                    Не знаю, мне нравится
                                    Все лучше чем писать два раза тип
                                    Ответить
                                    • >Все лучше чем писать два раза тип

                                      В яве (если не используешь lombok.val) ты пишешь тип 1 (один) раз
                                      List<Integer> a=Arrays.asList(1,2,3);
                                      
                                      List<String> a=new ArrayList<>();
                                      
                                      В C# тип в генерике не выводится
                                      var strings = new List<string> {"first", "second"};
                                      //<string> мог бы и додуплить


                                      val полезен только в случае паровозов из генериков: AbstractMap<Sting,List<Integer>>

                                      >fun foo()=123
                                      Что за язык?
                                      Ответить
                                      • Ты же сам List написал два раза

                                        Язык котлин

                                        fun foo(bar:Integer)=bar +42

                                        val buz=listOf(foo(12), 100050)

                                        buz теперь лист интов
                                        Ответить
                                        • Ща Роман пояснит что это не вывод типов, а говно

                                          А не говно есть сами знаете в каких япах уже 50 лет как
                                          Ответить
    • Засунул тебе в жопу резиновый член, зачекай!
      Ответить
    • Засунул тебе в жопу резиновый член, зачекай!
      Ответить
    • Засунул тебе в жопу резиновый член, зачекай!
      Ответить
    • Засунул тебе в жопу резиновый член, зачекай!
      Ответить
    • Засунул тебе в жопу резиновый член, зачекай!
      Ответить
    • >эти туповатые комментарии one dream, one soul это отсылка к песне Queen - A Kind of Magic

      /* one dream */
      /* one soul */
      /* one prize */
      /* one goal */

      По-моему эта песня отсылка к другой песне: Ein Volk, Ein Reich, Ein Führer
      Ответить

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