Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Fastest way to single hex digit => decimal

Name: Anonymous 2012-01-06 8:46

char hexchartodec_map[256] = {
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
        0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
};

char hexchartodec(char i) {
        return hexchartodec_map[i];
}

Name: Anonymous 2012-01-06 8:51

Cool tip.

Name: Anonymous 2012-01-06 8:54

Implying table lookups will not rape my precious cache.
What are you, twelve?

Name: Anonymous 2012-01-06 10:38

Implying 256 bytes will rape anyone is cache
What is this, 1993?

Name: Anonymous 2012-01-06 10:53

That's how I implemented the popcnt instruction without the actual instruction.

Name: Anonymous 2012-01-06 11:04

hexToDec c = let x = ord c
  in ( (x .&. 0xf)      * ((x .&. 0x10) `shiftR` 4))
   + (((x .&. 0xf) + 9) * ((x .&. 0x40) `shiftR` 6))

Name: Anonymous 2012-01-06 11:05

It is not a matter of size, the fact that the table will end up in the data segment is enough to create misses if your program does something else than calling that function.

But you guys inspired me, so I attempted to fool around with the ascii table layout:

/**
 * Assuming c is in "0123456789abcdef", the result will be wrong otherwise.
 */
char hexchartodec(const char c) {
    char d = c - '0';
    /* This if kind of means c >= '@', the compiler can't assume that c < 128
     * (i also can't do that, but i don't give a fuck) */
    if (c & 0x40) { //c to avoid a pipeline stall (we will have more below)
        /* The point here is that ('1'+16='A')+32='a'.*/
        --d; //or maybe d = c - '1';
        d &= 0xf; /* from the alignment of the ascii table, the least
                   * significant decimal is ready */
        d += 10;
    }
    return d;
}


However I couldn't get rid of the if and there are stalls inside the if as well. I'm sure that someone has a completly obsfucated version that does better than mine.

Name: Anonymous 2012-01-06 11:22

>>7
How do you figure that

if (c & 40)

avoids a pipeline stall

Name: Anonymous 2012-01-06 11:52

>>8
c & 0x40 does not depend on the result of d = c- '0';
However that comment is a left over from earlier when I wrote if (d >= 10) where there would be stall because (almost)all instructions from d >=10 would directly or indirectly depend on the result of the previous statement whose instructions are stil being executed.

But i didn't avoided the cpu from doing a wrong prediction of the branch that the if will produce which is way worse than using d inside the if.

Anyways, when i say stall on that comments (and here) i say that there are c statements that depend on each other and the compiler and cpu most likely won't be able to avoid stalls because there are no other alternative for rescheduling the instructions that do that statements.

>>6 Sugestion is pretty neat (with repect to the cpu pipeline as well) and unless the cpu takes too long to multiply or your compiler and cpu are too dumb that might faster (and also looks kinda cool)

Name: Anonymous 2012-01-06 12:36

There's a really short on x86 using das.

Someone figured out a long time ago that das performs the comparison and subtraction of 6 automatically...

Name: Anonymous 2012-01-06 12:42

>>10
This highly underrated instruction is invalid in x86-64, so fuck it.

Name: Anonymous 2012-01-06 12:49

x86-64
I'd sooner go to MIPS than use that horrible extension of x86.

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-06 14:01

something like this(this is untested, i don;t have time for compiling right now)
#define decbyte(x) ((x&0x40)<<3)+((x&0x40)<<1)+(x&0xf))

Name: Anonymous 2012-01-06 14:04

>>13

BROKEN PIECE OF SHIT MACRO ABUSE


decbyte(x++);

Name: Anonymous 2012-01-06 14:13

>>6
GHC -S -O:
    movq %r14,%rax
    movq %rax,%rcx
    andq $64,%rcx
    sarq $6,%rcx
    movq %rax,%rdx
    andq $15,%rdx
    addq $9,%rdx
    imulq %rcx,%rdx
    movq %rax,%rcx
    andq $16,%rcx
    sarq $4,%rcx
    movq %rax,%rbx
    andq $15,%rbx
    imulq %rcx,%rbx
    addq %rdx,%rbx
    jmp *0(%rbp)


GCC -march=core2 -O4 -S (on a simple C conversion taking unsigned char and returning unsigned int):
    movzbl  %dil, %edi
    movl    %edi, %edx
    movl    %edi, %eax
    andl    $64, %edi
    andl    $16, %edx
    andl    $15, %eax
    sarl    $6, %edi
    sarl    $4, %edx
    imull   %eax, %edx
    addl    $9, %eax
    imull   %edi, %eax
    addl    %edx, %eax
    ret

Name: Anonymous 2012-01-06 14:16

>>15
GHC -fvia-c -S -O:
    movq    %r14, %rax
    movq    %r14, %rdx
    andl    $15, %edx
    movq    %r14, %rcx
    andl    $16, %ecx
    sarq    $4, %rcx
    imulq   %rdx, %rcx
    andl    $64, %eax
    sarq    $6, %rax
    addq    $9, %rdx
    imulq   %rax, %rdx
    leaq    (%rcx,%rdx), %rbx
    jmp *0(%rbp)

Name: Anonymous 2012-01-06 14:53

>>15,16
I can't read that retarded syntax, but multiplication? Really?

Name: Anonymous 2012-01-06 14:57

>>3
[quote]implying it looks anything up[/quote]

Name: Anonymous 2012-01-06 15:00

>>17
Trying to get rid of it with direct bit shitting.

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-06 15:13

this should be a couple cycles faster (x>>6+((x>>6)<<3))+(x&0xf)

Name: Anonymous 2012-01-06 15:17

>>19
My idea failed:
1. BT to set CF if flag is set.
2. SALC to set AL to 0xFF if CF set.
3. AND with something.
4. Repeat for other bit.
5. ADD.

Only problem is that SALC is undocumented and doesn't work in my processor (tried .byte 0xD6).

Name: Anonymous 2012-01-06 15:23

>>20
No one cares about you FrozenShit, take your shitty code elsewhere

Name: Anonymous 2012-01-06 17:54

DCL DD BINARY-NUMBER BIN(2);
DCL DD DECIMAL-NUMBER PKD(2);
DCL DD INPUT-CHARACTER CHAR(1);
XLATE INPUT-CHARACTER, INPUT-CHARACTER, 'ABCDEF', 'abcdef';
SCAN BINARY-NUMBER, '0123456789abcdef', INPUT-CHARACTER/ZER(=+2);
SUBN(S) BINARY-NUMBER, 1;:
CPYNV DECIMAL-NUMBER, BINARY-NUMBER;

Name: Anonymous 2012-01-06 21:23

>>21
Try sbb al, al. What processor is that, SALC has been there since 8086.

Name: Anonymous 2012-01-06 22:10

python version:

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>;.

def hex_char_to_decimal_value(h):
   if h == "0":
      return 0
   elif h == "1":
      return 1
   elif h == "2":
      return 2
   elif h == "3":
      return 3
   elif h == "4":
      return 4
   elif h == "5":
      return 5
   elif h == "6":
      return 6
   elif h == "7":
      return 7
   elif h == "8":
      return 8
   elif h == "9":
      return 9
   elif h == "A" or h == "a":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("0")))
   elif h == "B" or h == "b":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("1")))
   elif h == "C" or h == "c":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("2")))
   elif h == "D" or h == "d":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("3")))
   elif h == "E" or h == "e":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("4")))
   elif h == "F" or h == "f":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("5")))

Name: Anonymous 2012-01-06 22:19

>>25
Holy fuck, that is, by far, the worst program in this thread. You've obviously only used HLLs before and have no idea about optimisation. Please proceed to fuck yourself with a rake.

Name: Anonymous 2012-01-06 22:25

>>25
Having this posted, let's see some benchmarks.

Name: Anonymous 2012-01-06 22:31

/[^0-9A-Fa-f]/{c\
Input a valid hex digit, ``faggot.''
q
}
y/ABCDEF/abcdef/
/[a-f]/{
     s/^/1/
     y/abcdef/012345/
}

Name: Anonymous 2012-01-06 22:34

>>27
delan@pluto /tmp $ time echo -e 'from dicks25 import *\nfor i in range(100000):\n\thex_char_to_decimal_value("f")' | python

real    0m2.504s
user    0m2.430s
sys     0m0.070s
delan@pluto /tmp $ cc -o cocks1 cocks1.c
delan@pluto /tmp $ time ./cocks1

real    0m0.005s
user    0m0.000s
sys     0m0.000s


As you can see, the >>1 solution beats >>25 ridiculously for 100000 iterations. The >>1 solution takes less time than is accurately measurable by time, even. The cocks1.c file contains >>1 plus this line:

main() { int i; for (i++ < 100000) hexchartodec('F'); }

Name: Anonymous 2012-01-06 23:16

>>25
GPL

freedom at all costs scum

use MIT or BSD next time

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-07 2:02

benchmarks:
#include <stdio.h>
#define u1 unsigned char
#define u2 unsigned short
#define u4 unsigned int
#define u8 unsigned long long
#define s1 signed char
#define s2 signed short
#define s4 signed int
#define s8 signed long long
#define f2 short float
#define f4 float
#define f8 double
#define f10 long double
#define hexchartodec3(x) (((x>>6)+((x>>6)<<3))+(x&0xf))
u8 inline rdtsc(){__asm{RDTSC}}
char hexchartodec_map[256] = {
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    };

char hexchartodec(char i) {
        return hexchartodec_map[i];
}
char hexchartodec2(const char c) {
    char d = c - '0';
    /* This if kind of means c >= '@', the compiler can't assume that c < 128
     * (i also can't do that, but i don't give a fuck) */
    if (c & 0x40) { //c to avoid a pipeline stall (we will have more below)
        /* The point here is that ('1'+16='A')+32='a'.*/
        --d; //or maybe d = c - '1';
        d &= 0xf; /* from the alignment of the ascii table, the least
                   * significant decimal is ready */
        d += 10;
    }
    return d;
}
char  hexchartodec4(char i){
switch(i){//since multiple IFS in chain are retarded
case '0':;return 0;
case '1':;return 1;
case '2':;return 2;
case '3':;return 3;
case '4':;return 4;
case '5':;return 5;
case '6':;return 6;
case '7':;return 7;
case '8':;return 8;
case '9':;return 9;
case 'a':;return 10;
case 'b':;return 11;
case 'c':;return 12;
case 'd':;return 13;
case 'e':;return 14;
case 'f':;return 15;
default:return 0;
}


}
main(s4 argc,s1**argv){
u8 start=rdtsc(),end=rdtsc();//rdtsc_delay ~85 cycles;


s1 n1,n2,n3,n4;
//hexchartodec   
start=rdtsc();
n1=hexchartodec('1');
n2=hexchartodec('f');
n3=hexchartodec('d');
n4=hexchartodec('5');
end=rdtsc();
printf("hexchartodec(Post >>1) Chars:%d,%d,%d,%d time:%llu cycles\n",n1,n2,n3,n4,(end-start));
//hexchartodec2
start=rdtsc();
n2=hexchartodec2('1');
n1=hexchartodec2('f');
n4=hexchartodec2('d');
n3=hexchartodec2('5');
end=rdtsc();
printf("hexchartodec2(Post >>7) Chars:%d,%d,%d,%d time:%llu cycles\n",n2,n1,n4,n3,(end-start));
//hexchartodec3
start=rdtsc();
n3=hexchartodec3('1');
n2=hexchartodec3('f');
n4=hexchartodec3('d');
n1=hexchartodec3('5');
end=rdtsc();
printf("hexchartodec3(Post >>20) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));
//hexchartodec4start=rdtsc();
n3=hexchartodec4('1');
n2=hexchartodec4('f');
n4=hexchartodec4('d');
n1=hexchartodec4('5');
end=rdtsc();
printf("hexchartodec4(Post >>25) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));
/*
C:\Program Files\dmc8.50\dmc\dm\bin\code>hex
hexchartodec(Post >>1) Chars:1,15,13,5 time:325 cycles
hexchartodec2(Post >>7) Chars:1,15,13,5 time:1572 cycles
hexchartodec3(Post >>20) Chars:1,15,13,5 time:85 cycles
hexchartodec4(Post >>25) Chars:1,15,13,5 time:988060 cycles
*/


}

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-07 2:12

fixed the hexchartodec4
C:\Program Files\dmc8.50\dmc\dm\bin\code>hex
hexchartodec(Post >>1) Chars:1,15,13,5 time:414 cycles
hexchartodec2(Post >>7) Chars:1,15,13,5 time:1866 cycles
hexchartodec3(Post >>20) Chars:1,15,13,5 time:85 cycles
hexchartodec4(Post >>25) Chars:1,15,13,5 time:2566 cycles

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-07 2:13

#include <stdio.h>
#define u1 unsigned char
#define u2 unsigned short
#define u4 unsigned int
#define u8 unsigned long long
#define s1 signed char
#define s2 signed short
#define s4 signed int
#define s8 signed long long
#define f2 short float
#define f4 float
#define f8 double
#define f10 long double
#define hexchartodec3(x) (((x>>6)+((x>>6)<<3))+(x&0xf))
u8 inline rdtsc(){__asm{RDTSC}}
char hexchartodec_map[256] = {
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    };

char hexchartodec(char i) {
        return hexchartodec_map[i];
}
char hexchartodec2(const char c) {
    char d = c - '0';
    /* This if kind of means c >= '@', the compiler can't assume that c < 128
     * (i also can't do that, but i don't give a fuck) */
    if (c & 0x40) { //c to avoid a pipeline stall (we will have more below)
        /* The point here is that ('1'+16='A')+32='a'.*/
        --d; //or maybe d = c - '1';
        d &= 0xf; /* from the alignment of the ascii table, the least
                   * significant decimal is ready */
        d += 10;
    }
    return d;
}
char  hexchartodec4(char i){
switch(i){//since multiple IFS in chain are retarded
case '0':;return 0;
case '1':;return 1;
case '2':;return 2;
case '3':;return 3;
case '4':;return 4;
case '5':;return 5;
case '6':;return 6;
case '7':;return 7;
case '8':;return 8;
case '9':;return 9;
case 'a':;return 10;
case 'b':;return 11;
case 'c':;return 12;
case 'd':;return 13;
case 'e':;return 14;
case 'f':;return 15;
default:return 0;
}


}
main(s4 argc,s1**argv){
u8 start=rdtsc(),end=rdtsc();//rdtsc_delay ~85 cycles;


s1 n1,n2,n3,n4;
//hexchartodec   
start=rdtsc();
n1=hexchartodec('1');
n2=hexchartodec('f');
n3=hexchartodec('d');
n4=hexchartodec('5');
end=rdtsc();
printf("hexchartodec(Post >>1) Chars:%d,%d,%d,%d time:%llu cycles\n",n1,n2,n3,n4,(end-start));
//hexchartodec2
start=rdtsc();
n2=hexchartodec2('1');
n1=hexchartodec2('f');
n4=hexchartodec2('d');
n3=hexchartodec2('5');
end=rdtsc();
printf("hexchartodec2(Post >>7) Chars:%d,%d,%d,%d time:%llu cycles\n",n2,n1,n4,n3,(end-start));
//hexchartodec3
start=rdtsc();
n3=hexchartodec3('1');
n2=hexchartodec3('f');
n4=hexchartodec3('d');
n1=hexchartodec3('5');
end=rdtsc();
printf("hexchartodec3(Post >>20) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));
//hexchartodec4start=rdtsc();
start=rdtsc();
n3=hexchartodec4('1');
n2=hexchartodec4('f');
n4=hexchartodec4('d');
n1=hexchartodec4('5');
end=rdtsc();
printf("hexchartodec4(Post >>25) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));


}

Name: Anonymous 2012-01-07 2:49

And now for ISO STANDARD C...
#include <string.h>
#include <errno.h>
#include <ctype.h>
int hex2dec(int c) {
    static const char *s = "0123456789ABCDEF";
    char *p;
    if (p = memchr(s, toupper(c), 16))
        return p - s;
    else {
        errno = EDOM;
        return -1;
    }
}


Or alternatively...
#include <stdlib.h>
int hex2dec(int c) {
    char s[2] = {c, '\0'};
    return strtol(s, NULL, 16);
}


On invalid input, the first one returns -1 and sets errno to EDOM. On invalid input, the second one returns 0 and, as a POSIX extension, may set errno to EINVAL.

Name: Anonymous 2012-01-07 2:49

here we go again

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-07 3:00

/*
C:\Program Files\dmc8.50\dmc\dm\bin\code>hex
hexchartodec(Post >>1) Chars:1,15,13,5 time:584 cycles
hexchartodec2(Post >>7) Chars:1,15,13,5 time:1243 cycl
hexchartodec3(Post >>20) Chars:1,15,13,5 time:90 cycle
hexchartodec4(Post >>25) Chars:1,15,13,5 time:3772 cyc
hex2dec(Post >>34) Chars:1,15,13,5 time:5921 cycles
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#define u1 unsigned char
#define u2 unsigned short
#define u4 unsigned int
#define u8 unsigned long long
#define s1 signed char
#define s2 signed short
#define s4 signed int
#define s8 signed long long
#define f2 short float
#define f4 float
#define f8 double
#define f10 long double
#define hexchartodec3(x) (((x>>6)+((x>>6)<<3))+(x&0xf))


int hex2dec(int c) {
    static const char *s = "0123456789ABCDEF";
    char *p;
    if (p = memchr(s, toupper(c), 16))
        return p - s;
    else {
        errno = EDOM;
        return -1;
    }
}




u8 inline rdtsc(){__asm{RDTSC}}
char hexchartodec_map[256] = {
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    };

char hexchartodec(char i) {
        return hexchartodec_map[i];
}
char hexchartodec2(const char c) {
    char d = c - '0';
    /* This if kind of means c >= '@', the compiler can't assume that c < 128
     * (i also can't do that, but i don't give a fuck) */
    if (c & 0x40) { //c to avoid a pipeline stall (we will have more below)
        /* The point here is that ('1'+16='A')+32='a'.*/
        --d; //or maybe d = c - '1';
        d &= 0xf; /* from the alignment of the ascii table, the least
                   * significant decimal is ready */
        d += 10;
    }
    return d;
}
char  hexchartodec4(char i){
switch(i){//since multiple IFS in chain are retarded
case '0':;return 0;
case '1':;return 1;
case '2':;return 2;
case '3':;return 3;
case '4':;return 4;
case '5':;return 5;
case '6':;return 6;
case '7':;return 7;
case '8':;return 8;
case '9':;return 9;
case 'a':;return 10;
case 'b':;return 11;
case 'c':;return 12;
case 'd':;return 13;
case 'e':;return 14;
case 'f':;return 15;
default:return 0;
}


}
main(s4 argc,s1**argv){
u8 start=rdtsc(),end=rdtsc();//rdtsc_delay ~85 cycles;


s1 n1,n2,n3,n4;
//hexchartodec   
start=rdtsc();
n1=hexchartodec('1');
n2=hexchartodec('f');
n3=hexchartodec('d');
n4=hexchartodec('5');
end=rdtsc();
printf("hexchartodec(Post >>1) Chars:%d,%d,%d,%d time:%llu cycles\n",n1,n2,n3,n4,(end-start));
//hexchartodec2
start=rdtsc();
n2=hexchartodec2('1');
n1=hexchartodec2('f');
n4=hexchartodec2('d');
n3=hexchartodec2('5');
end=rdtsc();
printf("hexchartodec2(Post >>7) Chars:%d,%d,%d,%d time:%llu cycles\n",n2,n1,n4,n3,(end-start));
//hexchartodec3
start=rdtsc();
n3=hexchartodec3('1');
n2=hexchartodec3('f');
n4=hexchartodec3('d');
n1=hexchartodec3('5');
end=rdtsc();
printf("hexchartodec3(Post >>20) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));
//hexchartodec4start=rdtsc();
start=rdtsc();
n3=hexchartodec4('1');
n2=hexchartodec4('f');
n4=hexchartodec4('d');
n1=hexchartodec4('5');
end=rdtsc();
printf("hexchartodec4(Post >>25) Chars:%d,%d,%d,%d time:%llu cycles\n",n3,n2,n4,n1,(end-start));
//hex2dec
start=rdtsc();
n4=hex2dec('1');
n1=hex2dec('f');
n2=hex2dec('d');
n3=hex2dec('5');
end=rdtsc();
printf("hex2dec(Post >>34) Chars:%d,%d,%d,%d time:%llu cycles\n",n4,n1,n2,n3,(end-start));



}

Name: Anonymous 2012-01-07 5:20

>>24
Thanks bro!  Works fine.  (Couldn't get SALC working on a cheap Core 2 processor.)
unsigned char
hexToDec2(unsigned char x)
{
    unsigned char output;

    asm(
        "mov $0xf,%%al;"
        "and %[input],%%al;"

        "bt $4,%[input];"
        "sbb %%bl,%%bl;"
        "and %%al,%%bl;"
        "mov %%bl,%[output];"

        "add $9,%%al;"
        "bt $6,%[input];"
        "sbb %%bl,%%bl;"
        "and %%al,%%bl;"
        "add %%bl,%[output];"

        : [output] "=X"(output)
        : [input] "X"(x)
        : "al", "bl");

    return output;
}

Name: Anonymous 2012-01-07 5:25

>>36
Copypaste code, looks like shit..

Name: F r o z e n V o i d !!mJCwdV5J0Xy2A21 2012-01-07 5:30

fixed style to abstract away the code blocks.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#define u1 unsigned char
#define u2 unsigned short
#define u4 unsigned int
#define u8 unsigned long long
#define s1 signed char
#define s2 signed short
#define s4 signed int
#define s8 signed long long
#define f2 short float
#define f4 float
#define f8 double
#define f10 long double
#define hexchartodec3(x) (((x>>6)+((x>>6)<<3))+(x&0xf))
#define timefunc(F)  ;start=rdtsc();n1=F('1');n2=F('f');n3=F('d');n4=F('5');end=rdtsc();printf("%s Chars:%d,%d,%d,%d time:%llu cycles\n",#F,n1,n2,n3,n4,(end-start));

int hex2dec(int c) {
    static const char *s = "0123456789ABCDEF";
    char *p;
    if (p = memchr(s, toupper(c), 16))
        return p - s;
    else {
        errno = EDOM;
        return -1;
    }
}




u8 inline rdtsc(){__asm{RDTSC}}
char hexchartodec_map[256] = {
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  10, 11, 12, 13, 14, 15, 0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
            0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    };

char hexchartodec(char i) {
        return hexchartodec_map[i];
}
char hexchartodec2(const char c) {
    char d = c - '0';
    /* This if kind of means c >= '@', the compiler can't assume that c < 128
     * (i also can't do that, but i don't give a fuck) */
    if (c & 0x40) { //c to avoid a pipeline stall (we will have more below)
        /* The point here is that ('1'+16='A')+32='a'.*/
        --d; //or maybe d = c - '1';
        d &= 0xf; /* from the alignment of the ascii table, the least
                   * significant decimal is ready */
        d += 10;
    }
    return d;
}
char  hexchartodec4(char i){
switch(i){//since multiple IFS in chain are retarded
case '0':;return 0;
case '1':;return 1;
case '2':;return 2;
case '3':;return 3;
case '4':;return 4;
case '5':;return 5;
case '6':;return 6;
case '7':;return 7;
case '8':;return 8;
case '9':;return 9;
case 'a':;return 10;
case 'b':;return 11;
case 'c':;return 12;
case 'd':;return 13;
case 'e':;return 14;
case 'f':;return 15;
default:return 0;
}}
main(s4 argc,s1**argv){
u8 start,end;//rdtsc_delay ~85 cycles;
s1 n1,n2,n3,n4;
timefunc(hexchartodec);
timefunc(hexchartodec2);
timefunc(hexchartodec3);
timefunc(hexchartodec4);
timefunc(hex2dec);
}

Name: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-01-07 6:28

>>36
Your compiler and CPU is horrible.

I had to redefine >>20 as a function to stop my compiler from simply substituting in the values, since they're all constants. With even first-level optimizations all of them take ~18 cycles (the RDTSC latency on my CPU) since the compiler optimizes away the code entirely. I also added a loop to repeat each one 1048576 (1M) times. These are all without optimization:

rdtsc latency: 27 cycles
hexchartodec(Post >>1) Chars:1,15,13,5 time:18016572 cycles/1M = 17.18 cycles/iteration
hexchartodec2(Post >>7) Chars:1,15,13,5 time:27049857 cycles/1M = 25.80 cycles/iteration
hexchartodec3(Post >>20) Chars:1,15,13,5 time:30027546 cycles/1M = 28.64 cycles/iteration
hexchartodec4(Post >>25) Chars:1,15,13,5 time:33271920 cycles/1M = 31.73 cycles/iteration
hex2dec(Post >>34) Chars:1,15,13,5 time:369429444 cycles/1M = 352.32 cycles/iteration
hexchartodec5(mine) Chars:1,15,13,5 time:14012856 cycles/1M = 13.36 cycles/iteration


Here's mine:

and al, 4fh
mov dl, al
mov cl, al
shr dl, 6
shr cl, 3
add al, dl
add al, cl
and al, 15

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List