Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
// 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
Это даже не битоёбство толком.
Просто разбили 64-битное деление на 2 32-битных.
>a = div10((unsigned int)(v >> 32));
>b = div10((unsigned int)(v & 0xffffffff));
Дистрибутивность для пятиклассников.
(hi+lo)/10 = hi/10+lo/10;
Вот интересенее div10 посмотреть. Там наверняка умножение на "магию".
Походу это особое деление на 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 назад научился оптимизировать деление на константы. Потому непонятно зачем писать весь этот код.
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");
}
А ну понятно. Они не хотят тянуть 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.
Кстати, кмк запороли простоту языка глупым исключением из своего же правила: не делать перегрузку операторов.
Использование "+" для конкатенации уже обсуждали. Уж лучше бы оставили конкатенацию м-м-максимально неудобной, а развивали либу, в тех местах где плюсики помогали быстро говнячить: sql, html, логгирование, формат-стринги.
Глядишь и говна меньше было бы: меньше бы клеили sqlи, а больше юзали prepared statement.
Меньше бы лепили тормозное логирование,
if (log.debugEnabled()){
log.debug("Hui: "+a+" pizda:"+b+" dzhigurga:"+c).
}
В яве (если не используешь 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>>
Просто разбили 64-битное деление на 2 32-битных.
>a = div10((unsigned int)(v >> 32));
>b = div10((unsigned int)(v & 0xffffffff));
Дистрибутивность для пятиклассников.
(hi+lo)/10 = hi/10+lo/10;
Вот интересенее div10 посмотреть. Там наверняка умножение на "магию".
И да этот __udivdi3 является более общим случаем(т.е. делить можно не только на 10, а на любую фигню), а в этом говнокоде особая заточенная реализация для деления именно на 10
Меня шмонай ты, вертухай,
Да загляни под юбочку,
Да посмотри на булочки.
Понюхай попку носиком,
Прикинься, киса, пёсиком,
Вот в этом вся и разница,
Кто хочет, а кто дразнится.
©Любимая группа мамки админа
Там деления вообще нет.
Но тут дело в том что gcc/clang давным-давно научились вычислять "магические числа" при компиляции, и заменять деление на умножение + сдвиг.
Даже жабовский hotspot лет 5 назад научился оптимизировать деление на константы. Потому непонятно зачем писать весь этот код.
https://godbolt.org/g/ddmtnj
Получаю imul (безо всяких флагов O2,O3):
"Умный" код с гитхаба.
0x66666667*2 = 0xccccccce
Тогда нормально.
> 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.
Джава вон про целый СтроительСтрок знает когда плюсик конпелит...
Использование "+" для конкатенации уже обсуждали. Уж лучше бы оставили конкатенацию м-м-максимально неудобной, а развивали либу, в тех местах где плюсики помогали быстро говнячить: sql, html, логгирование, формат-стринги.
Глядишь и говна меньше было бы: меньше бы клеили sqlи, а больше юзали prepared statement.
Меньше бы лепили тормозное логирование,
А больше юзали форматтеры:
Итд.
Перегрузка туда же относится.
Всё потому что 25 лет назад кто-то сказал "кококок, перегрузка усложняет код"
Есть, причём довольно приличный. Лучше чем в C#.
> в генерецию аксесоров/мутаторов
>датаклассы
Вывода типов нет. Напиши мне дефиницию переменной типа стринг, и сам увидишь
Это не очередная аоп-магия. К аоп вообще никакого отношения.
Это часть языка. Подключаешь обычный 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-код, распидорасив аннотации.
Вот вывод
var foo=12
val k = arrayOf(12,222)
Кмк эта говнофича обычно только убивает читабельность кода.
Ну если сильно хочется, то можно.
>val k = arrayOf(12,222)
Тем более фича неконсистентна return type в методе не выводит. Толк?
fun foo()=123
Не знаю, мне нравится
Все лучше чем писать два раза тип
В яве (если не используешь lombok.val) ты пишешь тип 1 (один) раз
val полезен только в случае паровозов из генериков: AbstractMap<Sting,List<Integer>>
>fun foo()=123
Что за язык?
Язык котлин
fun foo(bar:Integer)=bar +42
val buz=listOf(foo(12), 100050)
buz теперь лист интов
А не говно есть сами знаете в каких япах уже 50 лет как
Я засираю: ну нормально, знай поехали там, вся ворецировать, может с кем-нибудь организационным познакомлюсь там, нормально всё будет.
/* one dream */
/* one soul */
/* one prize */
/* one goal */
По-моему эта песня отсылка к другой песне: Ein Volk, Ein Reich, Ein Führer
int o;