1. C# / Говнокод #12800

    +142

    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
    protected static long chr2hex(char a)
    {
        switch (a)
        {
            case '0':
                return 0L;
            ...................
            case '9':
                return 9L;
            case 'A':
            case 'a':
                return 10L;
            .....................
            case 'F':
            case 'f':
                return 15L;
        }
        return 0L;
    }

    Как же это бесит, бля...

    Запостил: grobotron, 25 Марта 2013

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

    • Классика же. Тут хотя бы switch есть, уже прогресс.
      Ответить
    • > long
      В обычный int может не поместиться?
      Ответить
      • Заделка на будущее, под юникод же.
        Ответить
        • case '測':
              return 100500L;
          case '例':
              return 100501L;
          case '試':
              return 100502L;
          case '案':
              return 100503L;
          // to be continued...
          Ответить
        • Да и не просто под юникод, а под utf-64
          Ответить
          • utf-64 будет состоять из 64битных кусков... Для тех, кому 2^64 уже мало?
            Ответить
            • Представил себе файлы шрифтов. И дизайнера.
              Ответить
    • Еще круче было бы, если бы это был экстеншен метод!
      А так я уже валяюсь от полного перебора алфавита и чисел.
      Ответить
    • арифметику использовать некошерно,да?
      Ответить
      • Тем более, в шарпе даже можно это делать няшно в стиле С:
        return Char.IsDigit(a) ? a - '0' : Char.ToLower(a) - 'a' + 10;
        Ответить
        • А если там '#' или '$'?
          Ответить
        • в стиле С - не значит кратко, это значит быстро
          причем буквы дальше F как бы должны вернуть 0
          Ответить
        • А просто привести к типу int не няшно?
          Имхо, тоже говнокод.
          Ответить
        • return (a >= '0' && a <= '9') ? a - '0' : (a >= 'a' && a <= 'f') ? a - 'a' + 10 : (a >= 'A' && a <= 'F') ? a - 'A' + 10 : 0;
          Ответить
          • Здесь нужно Тарасоформатирование*:
            return (a >= '0' && a <= '9') ? a - '0'
                 : (a >= 'a' && a <= 'f') ? a - 'a' + 10
                 : (a >= 'A' && a <= 'F') ? a - 'A' + 10
                 :                          0;
            * http://govnokod.ru/12271#comment164033
            Ответить
            • а если чуток постараться, можно и головастика нарисовать
              return  (   a  >= '0' && a <= '9'
                       )  ? a - '0'      :
                      (   a  >= 'a' && a <= 'f'
                       )  ? a - 'a' + 10 :
                      (   a  >= 'A' && a <= 'F'
                       )  ? a - 'A' + 10 :
                       0                 ;
              Ответить
        • > в стиле С
          > Char.IsDigit(a)
          И сразу фейл.

          В стиле си брать чары из массива по 4 и конвертировать их в intе пачками по 2 или 4. В 64-х битном режиме скорость и того больше.
          К сожалению ни в жабе, ни в шарпе так стрелять нельзя. Чтоб быдло не стало БЕ3НОГNM
          Ответить
          • > Char.IsDigit
            http://ideone.com/CMuEae
            Ответить
          • открой секрет, как ты там нибблы пачками законвертишь?

            кстати, наброса ради, приведу канонiческую реализацию от CRT моей MSVC 9.1
            #define _ISDIGIT(chr)   isdigit((unsigned char)chr)
            #define _ISXDIGIT(chr)  isxdigit((unsigned char)chr)
            
            static _TINT __cdecl _hextodec ( _TCHAR chr)
            {
                return _ISDIGIT(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0');
            }
            ///....
                                                if (_ISXDIGIT(ch)) {
                                                    number = (number << 4);
                                                    ch = _hextodec(ch);
                                                }
            ///...
                                                number += ch - _T('0');
            понятное дело, что тут мегафункция, парсящая охулиард форматов и пацанам просто западло что-то сверхоптимизировать, но лично я для такой мегаузкой задачи, как конверт символа в ниббл написал бы статическую таблицу [256], в которой тупо в нужной ячейке лежит нужный результат
            Ответить
            • Интересно, а почему они сразу не вычли _T('0') внутри hextodec?
              Ответить
            • >chr & ~(_T('a') - _T('A'))
              Малаца, хорошо зделали. Я только хтел сказать что не надо проверять верхние и нижние отдельно.
              В ниббл сконвертить можно так
              x  = 0x06070A0F;
                  int d=	0x30303030, d1= 0x06060606,d2=0x10101010;
              	m    = x + d1;	
              	m &= d2;	
              	m >>= 4;
              	m  += (m<<2)+(m<<1);//тут не совсем оптимально. думаю можно лучше
              	x += d;
              	x += m; //now here '67AF'

              Или я ебанулся? Думаю кто-то уже должен был до такого додуматься.
              http://ideone.com/yT0BM9
              Парсинг - сложней. Нужно подрочиться с инвалидными значениями и нулями. Но тоже возможно.

              На 64-битном MMX регистре можно перегонять int32.
              А на SSE и вовсе 64-разрядные значения с явным профитом.
              Ответить
              • >m >>= 4;
                >m += (m<<2)+(m<<1)
                fix:
                m1 = m- ( (m>>4)^(m>>1) );
                    m1   ^= m<<1;// adds low-case. for example

                Хотя можно еще улучшить. Можно еще флаг ввести, который будет отвечать за большие/маленькие, но я сходу простого способа без ветвлений не вижу.
                Ответить
              • обсуждается же задача наоборот - '0' -> 0x0, 'a' -> 0xa, 'f' -> 0xf
                это и есть - чар в ниббл
                поставим четкие условия - надо из строки "67af" получить uint16_t 0x67af
                Ответить
                • >надо из строки "67af" получить uint16_t 0x67af
                  В SSE-регистрах это криво, потому что должно быть выровнено по байтам (который минимальная единица адресации): 0x06070a0f.
                  Но сдвигами это фиксится на раз.

                  >поставим четкие условия - надо из строки "67af" получить uint16_t 0x67af
                  Если я привел наглядный пример, то думаю не составит труда его обратить. Или вы думаете что обратный процесс сильно сложней?

                  Как я уже сказал его могут усложнить только проверки диапазонов.

                  >лично я для такой мегаузкой задачи, как конверт символа в ниббл написал бы статическую таблицу [256]
                  Но мы говорим в общем как делают "в стиле С". Понятно что для именно этой задачи, с вероятностью 95% этот hex пойдет в буфер и на вывод (который в тысячи раз тормознутей), то оптимизация не особо нужна.
                  Я же говорю об общем подходе - "в стиле С".
                  Ответить
                  • да почему на буфер то?
                    наоборот, из буфера читаем символ
                    раз уж мы тут обсуждаем SSE и обработку пачками, очевидно, что данные лежат в символьном виде в оперативе в удобном для обработки виде, тысячи их
                    допустим все по 8 символов, которые превращаются uint32_t, если тебе удобней - по 4 символа, которые превращаются в uint16_t
                    нелегальных символов нет
                    это не по правилам - но допустим, что вообще всё только в нижнем/верхнем (ненужное зачеркнуть) регистре

                    вот мне праздно интересно, даст ли молотилка SSE вообще профит перед решением в лоб (арифметический char -> nibble, скажем return ch < 'A' ? ch - '0' : ch - 'A' + 10; плюс 8(4) сдвига аккумулятора на << 4)
                    вопрос не тебе, а он вообще, риторический
                    Ответить
                    • Вот моя версия.
                      >что вообще всё только в нижнем/верхнем (ненужное зачеркнуть) регистре
                      Она понимает регистры. У Борманда судя по этому 0x20202020 - тоже.

                      https://ideone.com/L3Ktdg

                      >вот мне праздно интересно, даст ли молотилка SSE вообще профит перед решением в лоб
                      Да. Всего 8 комманд. Никаких ветвлений.
                      И обрабатываем сразу 16 байт.
                      Ответить
                    • >наоборот, из буфера читаем символ
                      Ну речь об том что задача чисто для I/O. А там, как известно, оптимизировать надо другое.
                      Ответить
                    • >раз уж мы тут обсуждаем SSE и обработку пачками, очевидно
                      >что данные лежат в символьном виде в оперативе
                      Прикол в том, что если будем грести по 128 бит, aligned ясен пень, такие загрузки очень сильно ускорят процесс, чем брать и ложить по одному чару. Там по-моему немного скорость снижается, если брать не кратное 32.
                      А обычно его потом еще и расширяют на все 32 зуба бита. И даже замена ветвлений на cmovы не сильно поможет.

                      Это еще одна статья ускорения. Думаю с версией борманда ниже, молотить будет раз в 15-20 быстрее. Что, в целом, существенный рывок. И труЪ способ для сишника.
                      Ответить
                      • Интересно только откуда возьмется столько хекс чисел, чтобы понадобилось привлекать ссе и такие способы...

                        Разве что какой-нибудь кривой сетевой протокол, в котором все текстом.
                        Ответить
                        • Может читаемая замена base64.
                          Я видел такую конвертацию говношифрованного бинарника в текстовый вид.
                          Ну кстати sse тогда еще бОльшую службу послужит.
                          Можно прямо там и дешифровать.

                          Да и в целом способ-то универсальный. Так еще задолго до sse паковали.
                          Ответить
                          • Кстати, а вот бейс64 интересно было бы забайтоебить. Но это намного сложнее чем хекс.
                            Ответить
                            • >а вот бейс64 интересно было бы забайтоебить
                              Да всё то же. Буквы, цифры, сдвиги. Основная трудность равно и другие символы.
                              Ну и то что base64 невыровнен по 2^n.
                              Ответить
                              • > Ну и то что base64 невыровнен по 2^n.
                                Ну это придется компенсировать бОльшим блоком - загружать по 16 символов и конвертить их в 12.

                                С равно можно поступить тупо - последний неполный блок обработать наивным методом.

                                Если между символов нет энтеров и прочего мусора - вроде сложностей больше и нет.
                                Ответить
                                • только обычно там хватает и энтеров и пробелов

                                  помню как наткнулся на дичайшую подставу в бусте для base64 - где то в недрах boost.archive, вроде, наш сотрудник наткнулся на енкод- и декод-итераторы, заюзал их и был несказанно рад
                                  а потом я разгребал эту багу - итераторы в бусте клали хер на возможную неполноту блока и тупо недоделывали буфер до конца
                                  Ответить
                            • >Но это намного сложнее чем хекс.
                              Оказалось что если начать делать, то нету ничего сложного.
                              int encodeBase64(int x){
                              	int r,low,num,extr;
                              	r		= 	x + 0x41;
                              	low		=	(x+38) & 0x40;
                              	r		+=	(low>>6)*6;
                              	num		=	(x+12) & 0x40;
                              	r		-=	num+(num>>6)*11;
                              	extr	=	(x+2) & 0x40;
                              	extr	>>=	2;
                              	r		-=	extr;
                              	extr	>>=	4;
                              	r		+=	(extr&x&1)*3+extr;
                              
                              	return r;
                              }

                              Остальное битоёбство с выранвиваниями слишком очевидно чтоб его делать.
                              http://ideone.com/40Q0cH
                              Ответить
                              • ничего не понятно
                                если тут забайтоёбен перевод 6 битов -> 1 символ, то такая тема всяко проиграет табличной замене
                                смысл примерно в том, чтобы 3 байта пачкой забайтоёбить в 4 символа (или 12 в 16, если так будет круче), и взад, чтобы обогнать табличный мэтод
                                Ответить
                                • >смысл примерно в том, чтобы 3 байта пачкой забайтоёбить в 4 символа

                                  Ну блин само собой. Я уж думал после стольких обсуждений всем будет очевидно как расширить мой пример на пачку.

                                  Вот думаю на декодингом.
                                  Причем если сам декодинг - Hurt me plenty, то проверка валидности - Nightmare.
                                  Ответить
                                  • т.е. предполагается вне функции func сделать разделение трех байт на четыре 6-битные части, сдвинуть три из них, на каждую часть натравить func, потом собрать результат в 4-байтном целом

                                    такая вундервафля ничего не обгонит, к сожалению :(
                                    Ответить
                                    • >делать разделение трех байт на четыре 6-битные части
                                      Да.
                                      > на каждую часть натравить func
                                      Расширить func. И натравить на все одновременно.
                                      >потом собрать результат в 4-байтном целом
                                      Он сам соберется.
                                      Ответить
                                    • >такая вундервафля ничего не обгонит, к сожалению :(

                                      Сделал типа рабочий кодер base64 для 64-битных слов.
                                      https://ideone.com/4XHkj6

                                      Вот как, блядь, нужно кодить, вот, быстро. Раз-раз-раз! Давай, кодь. Base64!
                                      Ответить
                                      • таперича расскажи как пользоваться, ибо
                                        https://ideone.com/lLR7MB
                                        выдает не то
                                        (должен "TWFuIGlz")

                                        пример взят из педовикии /Base64
                                        Ответить
                                        • Я реверс байт не сделал. Endianness, короче.
                                          Можно объединить его с expand (который сам по себе непоптимален), но мне влом.борманда проси у него лучше получается
                                          https://ideone.com/cG5svp
                                          Ответить
                          • ну в base64 есть и плюс, ведь 4/3 лучше 2/1
                            Ответить
                            • >ведь 4/3 лучше 2/1
                              xml и json сочли это преимущество сомнительным.
                              Правда наборы &#x160; &#x41; хер так просто попарсишь.
                              Ответить
                              • > сомнительным
                                ну так в &#x...; влезет то только целочисленное значение
                                туда не упихнуть 100500 байт бинарных данных
                                а уж целочисленное значение проще видеть глазами, понятное дело
                                Ответить
                                • Просто, наверное вы не видели упакованных в xml-е бинарных данных из таких вот &#x.
                                  Ответить
                                  • ну вот тут уже никаких преимуществ, одни только недостатки - раз в стандарте ничего про base64 не сказано, и раз сам особо не договорился - будь добр херачить бинарные данные по стандарту
                                    причем получится-то хуже 2/1:
                                    > provide a (hexa)decimal representation of the character's code point in ISO/IEC 10646
                                    т.е. в среднем для распространенного двухбайтового значения получится около 6 байт результата

                                    даже не просто бинарные данные - так только символы можно кодировать
                                    Ответить
                                    • >тут уже никаких преимуществ
                                      Ну да. Говно. Плюс один: легче сходу читать эти коды. Ну типично для xml - читаемость как у бинарного, размер и эффективность как у текстового.
                                      > получится-то хуже 2/1
                                      Так еще и невыровненое.

                                      >около 6 байт результата
                                      Как и в json: \uABCD.
                                      Ответить
                                      • > Как и в json: \uABCD.
                                        ну тут то максимум 6
                                        а в xml - максимум 8 - &#xXXXX;
                                        хорошо, прикид был неверный - в xml в среднем будет 7
                                        Ответить
                                        • >хорошо, прикид был неверный - в xml в среднем будет 7
                                          Как и в json: \\uABCD
                                          Ответить
                          • >Кстати, а вот бейс64 интересно было бы забайтоебить.
                            Декодинг base64 и самая хардкорная часть: проверка валидности.
                            http://ideone.com/xkizU4
                            inline
                            int correct(int x){
                                int b;
                            	a	= 	x &	0x40;
                            	b	=	a>>6	;
                            	return	x -	b	;
                            }
                            //check for errors
                            inline
                            int inValidBase64(int x){
                            	int i1,num;
                            	i1	=	correct(x);
                            	
                            	lo 	= 	(i1+5) ^ 0x80;
                            	num	=	lo;
                            	lo	&=	lo<<1;
                            	num	&=	lo<<2;
                            	int fm=	~(num | lo);
                            	//and num like 00x01000 //if (8==(num&(~32)))
                            	int s= i1 | 0x60;
                            	s +=6;
                            	return ((s | fm) & 0x80);
                            }
                            Ответить
                • Байтоебская версия в типичном байтоебском стиле (никаких проверок): https://ideone.com/iqObxf
                  Ответить
                  • Многовато, как-то. Но константы и код почти как у меня.
                    https://ideone.com/L3Ktdg
                    static int d=	0x30303030,b1=0x0F0F0F0F, d2=0x10101010;
                    
                    int fromHex(int hex){
                    	int m,m1;
                    	hex -= d;
                    	m 	 = hex & d2;
                    	m1 	 = m | (m << 1);	//low case
                    	hex	-= (m1>>3) ^ (m>>4);
                    	return hex & b1; //теор. это можно убрать. оставлю для надежности
                    }
                    Ответить
                    • Дык у меня там еще упаковка в нибблы с учетом little-endian. А сам перевод - 4 строчки, по идее даже короче получился:
                      a |= 0x20202020;
                      a -= 0x30303030;
                      int32_t b = a & 0xF0F0F0F0;
                      a += (b >> 4) + (b >> 3)
                      Ответить
                      • >там еще упаковка в нибблы с учетом little-endian
                        А, всё понял.

                        >по идее даже короче получился:
                        7 комманд. Круто.

                        А у них получится без проверок, для одного символа примерно столько же.
                        Но с ветвлениями, лол.
                        Ответить
                        • update (-1 операция):
                          a &= 0xCFCFCFCF;
                          unsigned int b = (a & 0x40404040) >> 3;
                          a += b + (b >> 3);
                          Ответить
                          • На сдвиге секономил:?
                            Ответить
                            • Нет, | и - объединил в одну. Сдвигов столько же.
                              Ответить
                              • Шото я сегодня туплю.
                                А-а-а теперь я понял откуда лишняя комманда больше было.
                                >return hex & b1; //теор. это можно убрать.

                                Я чищу перед возвратом, а у тебя очистка совмещена с перемешиванием байтов.
                                Ответить
                                • Смотри однострок ниже - 5 операций (mov, and, shr, lea, add).

                                  > -а-а теперь я понял почему у меня на одну комманду больше было.
                                  Нет. Лишняя команда была в lowcase.
                                  Ответить
                            • Ну и вроде как последний фикс и остается 5 операций:
                              unsigned int b = (a & 0x40404040) >> 3;
                              a += b + (b >> 3);
                              Однострочка (с надеждой на lea):
                              a += ((a & 0x40404040) >> 6) * 9;
                              Будем считать ее апофеозом? ;)
                              Ответить
                              • >Однострочка (с надеждой на lea):
                                Кстати этот вариает самый очевидный. И наверно надо & 0x0F0F0F0F делать.
                                Не путь джедаев-байтоебов надеятся на lea.

                                Крут-крут. Я совсем сегодня плохо соображаю.
                                Ответить
                                • & 0x0F0F0F0F нужен только если не будет упаковки, а так его лучше с ней и совместить.
                                  Ответить
                              • Может еще и упаковку попробуешь?
                                Я писал и думал как бы туда проверки впилить, но там адски, у нас три случая
                                a-0x30
                                00x1 - hex, который можно | сделать в 0011
                                0000 - цифра
                                Остальное - должно быть нулём. То есть надо верхние байты превратить в большую маску
                                Ответить
                              • Раньше борманд курил высокоуровневые абсракции на Хаскеле, а теперь курит низкоуровневые ассемблерные байтоёбства.

                                Не подскажите ли чего он такого курит?
                                Очевидно толстых хвостатых манулов.
                                Ответить
                                • >а теперь курит низкоуровневые ассемблерные байтоёбства.

                                  Ты тут недавно? Сначала было байтоебство. А ну да, именно ты и начал форсить тут хацкиль.
                                  Ответить
                                  • В начале было Слово, и Слово было это было Байтоёбством.
                                    Ответить
                                    • Борманд походу всё курит понемногу, кроме явно шаквареных: пыхи, 1С. И sqlя.
                                      Ответить
                                      • Шарпик еще не курю. А пых и скуль это необходимое зло. Юзать их могу, но для души в них совершенно ничего нет.
                                        Ответить
                                        • >Шарпик еще не курю.
                                          А кому он нужен? Я его тоже не курю. (только на уровне написать очередной коммент про AssParallel)
                                          Знание явы - на 50% знание шарпа.

                                          >для души в них совершенно ничего нет.
                                          В SQL там свои приколы, но надо идти вглубь: планы запросов, расположения индексов и таблиц, схемы блокировок.
                                          И каждый сервер - целая наука.
                                          Со своими заморочками и граблями.
                                          Ответить
                  • int toHex(int str){
                    	str &= 0x0F0F0F0F; 
                        int  m    = str + 0x06060606;	
                    	m1   = m-( (m>>4)+(m>>1) );
                    	return str += (0x10101010*3) + m1;
                    }

                    Не получается больше 8.
                    Ответить
                    • 7
                      static int d =0x10101010
                      , 		   lowB=0x0F0F0F0F;
                      int toHex(int str){
                      	str &= lowB;
                      	int m= str + 0x36363636;	
                      	m	&= d*4;
                      	m	+= m>>1;
                      	return str += d*3 + m;
                      }
                      Ответить
    • Зато за одну операцию.
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить

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