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: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-01-07 6:35

>>37
hexchartodec6(Post >>37) Chars:1,15,13,5 time:25221651 cycles/1M = 24.05 cycles/iteration

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

>>40
The whole point is to make a it macro, the function call overhead is really noticeable

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


hexchartodec7(mine) Chars:1,15,13,15 time:13011942 cycles/1M = 12.41 cycles/iteration



mov ah, al
and ah, 4
and al, 15
shr ah, 2
aad 9  // CISC IS AWESOME


Anyone want to go for <10 cycles?

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

You can try writing a better macro than >>20 // CISC IS UNPORTABLE

Name: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-01-07 7:25

>>44
hexchartodec3m(Post >>20, modified) Chars:1,15,13,5 time:25927290 cycles/1M = 24.73 cycles/iteration

#define hexchartodec3m(x) ((((x&64)>>3)+((x&64)>>6)+x)&15)

Slightly better than >>7 but still nowhere near OP (fastest but largest portable one --- on x86, that is) nor the asm versions.

Strangely enough xlatb isn't faster than OP's on x86, even though it's a specific table lookup instruction (and was kept in 64-bit mode, for some reason.)

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

>>45
>((((x&64)>>3)+((x&64)>>6)+x)&15)
That looks like >>13 i thought it was abit slower.
Also, the loop just calls the table in cache at full CPU speed in single opcode

Name: Anonymous 2012-01-07 8:03

unsigned int
hexToDec(unsigned char x)
{
    return ( (x & 0xf)      * ((x & 0x10) >> 4))
         + (((x & 0xf) + 9) * ((x & 0x40) >> 6));
}

Name: Anonymous 2012-01-07 8:27

Silly Cudder, still puts a whitespace betwixt his name and the hash character.
That's not how you should trip on world4ch silly Cudder!

Name: Cudder !MhMRSATORI!FBeUS42x4uM+kgp 2012-01-07 8:34

>>48
The 0x20 is part of my name.

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

>>47
This is A.Retarded B.Haskell
>>45
try to time this:
#define hexchartodec3m2(x) ((((x>>6)<<3)+(x>>6)+x)&15)

Name: Anonymous 2012-01-07 9:30

>>49
That's not very portable of you, I mean a whitespace is a whitespace but 0x20 is only ASCII and supersets of it.

Name: Anonymous 2012-01-07 9:38

>>51
But it's not a "whitespace", it's a "0x20" byte.

Name: Anonymous 2012-01-07 9:42

>>50
This is A.Retarded B.Haskell
C.Fast.

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

>>53
>C.Fast
The macro is order of magnitude faster(no function calls, no multiplies, no implied casts to char).
The braindead switch/ifs from python is faster.
The table is obviously faster.

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

/*
C:\Program Files\dmc8.50\dmc\dm\bin\code>hex
hexchartodec Chars:1,15,13,5 time:403 cycles
hexchartodec2 Chars:1,15,13,5 time:1819 cycles
hexchartodec3 Chars:1,15,13,5 time:87 cycles
hexchartodec4 Chars:1,15,13,5 time:2446 cycles
hex2dec Chars:1,15,13,5 time:5976 cycles
hexchartodec3m Chars:1,15,13,5 time:119 cycles
hexToDec Chars:1,15,13,5 time:2047 cycles
hexchartodec3m2 Chars:1,15,13,5 time:95 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))
#define hexchartodec3m(x) ((((x&64)>>3)+((x&64)>>6)+x)&15)
unsigned int
hexToDec(unsigned char x)
{
    return ( (x & 0xf)      * ((x & 0x10) >> 4))
         + (((x & 0xf) + 9) * ((x & 0x40) >> 6));
}
#define hexchartodec3m2(x) ((((x>>6)<<3)+(x>>6)+x)&15)
#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);// >>1
timefunc(hexchartodec2);//>>7
timefunc(hexchartodec3);//>>20
timefunc(hexchartodec4);//>>25
timefunc(hex2dec);//>>34
timefunc(hexchartodec3m);//>>45
timefunc(hexToDec);//>>47
timefunc(hexchartodec3m2);//>>50
}

Name: 2012-01-07 10:07

Name: Anonymous 2012-01-07 10:14

>>54,55
Must be some bug in your compiler (compiled without optimization flags in GCC 4.6.2;  I changed the result and parameter type to char for extra speed (from ~180 cycles)):

hexchartodec Chars:1,15,13,5 time:162 cycles
hexchartodec2 Chars:1,15,13,5 time:297 cycles
hexchartodec3 Chars:1,15,13,5 time:81 cycles
hexchartodec4 Chars:1,15,13,5 time:360 cycles
hex2dec Chars:1,15,13,5 time:14139 cycles
hexchartodec3m Chars:1,15,13,5 time:81 cycles
hexToDec Chars:1,15,13,5 time:162 cycles
hexchartodec3m2 Chars:1,15,13,5 time:90 cycles

Name: Anonymous 2012-01-07 10:21

And if you make it a macro it gets as fast as any of the others.

hexToDec Chars:1,15,13,5 time:81 cycles

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

/*
C:\Program Files\dmc8.50\dmc\dm\bin\code>hex
hexchartodec Chars:1,15,13,5 time:485 cycles
hexchartodec2 Chars:1,15,13,5 time:3164 cycles
hexchartodec3 Chars:1,15,13,5 time:73 cycles
hexchartodec4 Chars:1,15,13,5 time:3422 cycles
hex2dec Chars:1,15,13,5 time:11459 cycles
hexchartodec3m Chars:1,15,13,5 time:85 cycles
hexToDec Chars:1,15,13,5 time:2558 cycles
hexchartodec3m2 Chars:1,15,13,5 time:91 cycles
hexToDecChar Chars:1,15,13,5 time:3277 cycles
macroHexToDecChar Chars:1,15,13,5 time:78 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))
#define hexchartodec3m(x) ((((x&64)>>3)+((x&64)>>6)+x)&15)
unsigned int
hexToDec(unsigned char x)
{
    return ( (x & 0xf)      * ((x & 0x10) >> 4))
         + (((x & 0xf) + 9) * ((x & 0x40) >> 6));
}

char hexToDecChar(char x)
{
    return ( (x & 0xf)      * ((x & 0x10) >> 4))
         + (((x & 0xf) + 9) * ((x & 0x40) >> 6));
}
#define macroHexToDecChar(x) ( (x & 0xf)      * ((x & 0x10) >> 4))   + (((x & 0xf) + 9) * ((x & 0x40) >> 6))
#define hexchartodec3m2(x) ((((x>>6)<<3)+(x>>6)+x)&15)
#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);// >>1
timefunc(hexchartodec2);//>>7
timefunc(hexchartodec3);//>>20
timefunc(hexchartodec4);//>>25
timefunc(hex2dec);//>>34
timefunc(hexchartodec3m);//>>45
timefunc(hexToDec);//>>47
timefunc(hexchartodec3m2);//>>50
timefunc(hexToDecChar);
timefunc(macroHexToDecChar);
}

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

rdtsc is bit unreliable for exact cycle count, but it reflects the execution process opcode cost more than any artificial loop/function abstraction.

Name: Anonymous 2012-01-07 15:19

>>59
Please take your shitty broken macro abuse back to /g/

Name: Anonymous 2012-01-07 15:39

>>61
Actually, I believe /prog/ is the perfect place for something like that.

Name: Anonymous 2012-01-07 15:58

>>25 here

i did some profiling and optimized this according to how often i have encountered the hex values in various files

# 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 == "F" or h == "f":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("5")))
   elif h == "1":
      return 1
   elif h == "2":
      return 2
   elif h == "4":
      return 4
   elif h == "8":
      return 8
   elif h == "5":
      return 5
   elif h == "7":
      return 7
   elif h == "E" or h == "e":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("4")))
   elif h == "3":
      return 3
   elif h == "6":
      return 6
   elif h == "9":
      return 9
   elif h == "D" or h == "d":
      return int(str(hex_char_to_decimal_value("1")) + str(hex_char_to_decimal_value("3")))
   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")))

Name: Anonymous 2012-01-07 16:03

>>63
Please do not post your freedom at all costs GPL code here.

use MIT/BSD or public domain, ``faggot''

Name: Anonymous 2012-01-07 16:05

>>64
if you would like to purchase a commercial license for the above code, this option will be available soon!

Name: Anonymous 2012-01-07 16:11

>>65'
>purchasing shitty python code
>purchasing shitty unoptimized code
>purchasing long elif shitty code


no one cares about your shitty code

Name: Anonymous 2012-01-07 16:12

>>66
You must be proud of your h4xx0r 4chun qu0t1ng sk1llz.

Name: Anonymous 2012-01-07 16:15

>>67
back to /g/ with you

Name: Anonymous 2012-01-07 17:36

Just use a hashmap if you want speed.  This is what I use in my game code:


HashMap<Character, Integer> hexMap = new HashMap<Character, Integer> (16); // Initialize this to 16 for speed

hexMap.put('0', 0);
hexMap.put('1', 1);
hexMap.put('2', 2);
hexMap.put('3', 3);
hexMap.put('4', 4);
hexMap.put('5', 5);
hexMap.put('6', 6);
hexMap.put('7', 7);
hexMap.put('8', 8);
hexMap.put('9', 9);
hexMap.put('A', 10 + 0);
hexMap.put('B', 10 + 1);
hexMap.put('C', 10 + 2);
hexMap.put('D', 10 + 3);
hexMap.put('E', 10 + 4);
hexMap.put('F', 10 + 5);

if (hexMap.contains(new Character(c))) {
   return hexMap.get(new Character(c));
} else {
   throw new InvalidHexException(new String(c) + " is not a valid hex character");
}

Name: Anonymous 2012-01-07 17:53

>>69
LOLWUT
int[] hexMap = new int[256];
hexMap['0'] = 0;
hexMap['1'] = 1;
hexMap['2'] = 2;
hexMap['3'] = 3;
hexMap['4'] = 4;
hexMap['5'] = 5;
hexMap['6'] = 6;
hexMap['7'] = 7;
hexMap['8'] = 8;
hexMap['9'] = 9;
hexMap['A'] = 10;
hexMap['B'] = 11;
hexMap['C'] = 12;
hexMap['D'] = 13;
hexMap['E'] = 14;
hexMap['F'] = 15;

int parse(char c) {
  return hexMap[c];
}

Name: Anonymous 2012-01-07 17:55

>>70 which is the same thing that OP wrote

Name: Anonymous 2012-01-07 18:08

ITT FrozenVoid doesn't know what inlining is

Name: Anonymous 2012-01-07 18:22

>>63

You know, it would be much better to just use python's built in utility
>>>int("ff", 16)
output: 255


Ruby has one too
"ff".to_i(16)

Name: Anonymous 2012-01-07 18:23

>>72 He uses dmc, and wants to be a compiler like that.

Name: Anonymous 2012-01-07 18:25

>>73
So does C:
strtol("ff", NULL, 16);

Name: Anonymous 2012-01-07 18:35

>>73
[d@home ~]$ time echo '1000000.times do "ff".to_i(16) end' | ruby
real    0m0.359s
user    0m0.353s
sys    0m0.003s
[d@home ~]$ time echo 'for i in range(1000000): int("ff",16)' | python
real    0m0.724s
user    0m0.710s
sys    0m0.013s

Name: Anonymous 2012-01-07 18:38

>>74
He's a self-taught `expert' programmer
He doesn't know the C standard
He abuses macros
He's dumb

Name: Anonymous 2012-01-07 18:39

>>73,76
[d@home ~]$ time echo 'main(){ int i; for(i=0;i<1000000;i++) strtol("ff", 0, 16); }' | gcc -xc -
real    0m0.271s
user    0m0.063s
sys    0m0.033s
[d@home ~]$ time echo 'main(){ int i; for(i=0;i<1000000;i++) strtol("ff", 0, 16); }' | gcc -xc -
real    0m0.047s
user    0m0.023s
sys    0m0.017s

even with compilation time it's still faster

Name: Anonymous 2012-01-07 18:45

>>78

Because it's fucking C. We know.

Name: Anonymous 2012-01-07 18:50

>>70
That has one major bug.  If you pass in '!' you get the value zero, when it should throw an exception.

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