View difference between Paste ID: YDWg0Lsb and XSiPqHuN
SHOW: | | - or go back to the newest paste.
1
#include <stdio.h>
2
#include <time.h>
3
#include <vector>
4
#include <string>
5
#include <algorithm>
6
#include <smmintrin.h>
7
#include <stdint.h>
8
#include <string.h>
9
#ifdef _MSC_VER
10-
UINT32 GetIP(const char *p)
10+
	#define ALIGN(n) __declspec(align(n))
11
#else
12
	#define ALIGN(n) __attribute__((aligned(n)))
13
#endif
14
15
typedef unsigned int UINT32;
16
17
//=============================================== original =================================================
18
19
inline UINT32 GetIP(const char *p)
20
{
21
    UINT32 dwIP=0,dwIP_Part=0;
22
    while(true)
23
    {
24
        if(p[0] == 0)
25
        {
26
            dwIP = (dwIP << 8) | dwIP_Part;
27
            break;
28
        }
29
        if(p[0]=='.') 
30
        {       
31
            dwIP = (dwIP << 8) | dwIP_Part;                     
32-
__m128i shuffleTable[65536];    //perhaps can be reduced 32x times, see @IwillnotexistIdonotexist
32+
33
           p++;
34
        }
35
        dwIP_Part = (dwIP_Part*10)+(p[0]-'0');
36
        p++;
37
    }
38
    return dwIP;
39
}
40
41
//=============================================== stgatilov =================================================
42
43
__m128i shuffleTable[65536];    //can be reduced 256x times, see solution by @IwillnotexistIdonotexist below
44
void MyInit() {
45
    memset(shuffleTable, -1, sizeof(shuffleTable));
46
    int len[4];
47
    for (len[0] = 1; len[0] <= 3; len[0]++)
48
        for (len[1] = 1; len[1] <= 3; len[1]++)
49
            for (len[2] = 1; len[2] <= 3; len[2]++)
50
                for (len[3] = 1; len[3] <= 3; len[3]++) {
51
                    int slen = len[0] + len[1] + len[2] + len[3] + 4;
52
                    int rem = 16 - slen;
53
                    for (int rmask = 0; rmask < 1<<rem; rmask++) {
54
//                    { int rmask = (1<<rem)-1;    //note: only maximal rmask is possible if strings are zero-padded
55
                        int mask = 0;
56
                        char shuf[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
57
                        int pos = 0;
58
                        for (int i = 0; i < 4; i++) {
59
                            for (int j = 0; j < len[i]; j++) {
60-
UINT32 MyGetIP(const char *str) {
60+
61-
    __m128i input = _mm_lddqu_si128((const __m128i*)str);   //"192.167.1.3"
61+
62-
//  for (int i = 0; i < 16; i++) printf("%c ", input.m128i_u8[i]); printf("\n");
62+
63-
    input = _mm_sub_epi8(input, _mm_set1_epi8('0'));        //1 9 2 254 1 6 7 254 1 254 3 208 245 0 8 40 
63+
64-
//  for (int i = 0; i < 16; i++) printf("%d ", int(input.m128i_u8[i])); printf("\n");
64+
65-
    __m128i cmp = input;                                    //...X...X.X.XX...  (signs)
65+
66-
//  for (int i = 0; i < 16; i++) printf("%c", cmp.m128i_i8[i] < 0 ? 'X' : '.'); printf("\n");
66+
67-
    UINT32 mask = _mm_movemask_epi8(cmp);                   //6792 - magic index
67+
68-
//  printf("%d\n", mask);
68+
69-
    __m128i shuf = shuffleTable[mask];                      //10 -1 -1 -1 8 -1 -1 -1 6 5 4 -1 2 1 0 -1 
69+
70-
//  for (int i = 0; i < 16; i++) printf("%d ", int(shuf.m128i_i8[i])); printf("\n");
70+
71-
    __m128i arr = _mm_shuffle_epi8(input, shuf);            //3 0 0 0 | 1 0 0 0 | 7 6 1 0 | 2 9 1 0 
71+
inline UINT32 MyGetIP(const char *str) {
72-
//  for (int i = 0; i < 16; i++) printf("%d ", int(arr.m128i_u8[i])); printf("\n");
72+
	__m128i input = _mm_lddqu_si128((const __m128i*)str);
73-
    __m128i coeffs = _mm_set_epi8(0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1);
73+
//	for (int i = 0; i < 16; i++) printf("%c ", input.m128i_u8[i]); printf("\n");
74-
    __m128i prod = _mm_maddubs_epi16(coeffs, arr);          //3 0 | 1 0 | 67 100 | 92 100 
74+
	input = _mm_sub_epi8(input, _mm_set1_epi8('0'));
75-
//  for (int i = 0; i < 8; i++) printf("%d ", int(prod.m128i_u16[i])); printf("\n");
75+
//	for (int i = 0; i < 16; i++) printf("%d ", int(input.m128i_u8[i])); printf("\n");
76-
    prod = _mm_hadd_epi16(prod, prod);                      //3 | 1 | 167 | 192 | ? | ? | ? | ?
76+
	__m128i cmp = input;
77-
//  for (int i = 0; i < 4; i++) printf("%d ", int(prod.m128i_u16[i])); printf("\n");
77+
//	for (int i = 0; i < 16; i++) printf("%c", cmp.m128i_i8[i] < 0 ? 'X' : '.'); printf("\n");
78-
    __m128i imm = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 4, 2, 0);
78+
	uint64_t mask = _mm_movemask_epi8(cmp);
79-
    prod = _mm_shuffle_epi8(prod, imm);                     //3 1 167 192 0 0 0 0 0 0 0 0 0 0 0 0
79+
//	printf("%d\n", mask);
80-
//  for (int i = 0; i < 4; i++) printf("%d ", int(prod.m128i_u8[i])); printf("\n");
80+
	__m128i shuf = shuffleTable[mask];
81-
    return _mm_extract_epi32(prod, 0);
81+
//	for (int i = 0; i < 16; i++) printf("%d ", int(shuf.m128i_i8[i])); printf("\n");
82-
//  return (UINT32(_mm_extract_epi16(prod, 1)) << 16) + UINT32(_mm_extract_epi16(prod, 0)); //no SSE 4.1
82+
	__m128i arr = _mm_shuffle_epi8(input, shuf);
83
//	for (int i = 0; i < 16; i++) printf("%d ", int(arr.m128i_u8[i])); printf("\n");
84
	__m128i coeffs = _mm_set_epi8(0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1);
85
	__m128i prod = _mm_maddubs_epi16(coeffs, arr);
86
//	for (int i = 0; i < 8; i++) printf("%d ", int(prod.m128i_u16[i])); printf("\n");
87
	prod = _mm_hadd_epi16(prod, prod);
88
//	for (int i = 0; i < 4; i++) printf("%d ", int(prod.m128i_u16[i])); printf("\n");
89
	prod = _mm_shuffle_epi8(prod, _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 4, 2, 0));
90-
//  return 0;
90+
//	for (int i = 0; i < 4; i++) printf("%d ", int(prod.m128i_u8[i])); printf("\n");
91
	return _mm_extract_epi32(prod, 0);
92
//	return (UINT32(_mm_extract_epi16(prod, 1)) << 16) + UINT32(_mm_extract_epi16(prod, 0));
93
}
94
95
//==================================== @IwillnotexistIdonotexist ===============================================
96
//lookup table is compressed to 4Kb
97
//taken from http://pastebin.com/XJ7w9nq1
98
99
ALIGN(16) const char TBL[256][16] = {
100
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
101
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
102
	{  8,  -1,  -1,  -1,   6,  -1,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
103
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
104
	{ 10,  -1,  -1,  -1,   8,   7,   6,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
105-
    auto a = GetIP(samples.back().c_str());
105+
	{  9,  -1,  -1,  -1,   7,  -1,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
106-
    auto b = MyGetIP(samples.back().c_str());
106+
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
107-
    if (a != b)
107+
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
108-
      printf("%s: %08X vs %08X\n", samples[i].c_str(), a, b);
108+
	{  9,  -1,  -1,  -1,   7,   6,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
109-
        
109+
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
110
	{ 12,  11,  10,  -1,   8,   7,   6,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
111
	{ 10,  -1,  -1,  -1,   8,  -1,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
112
	{ 12,  11,  10,  -1,   8,  -1,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
113
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
114
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
115
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
116
	{ 10,  -1,  -1,  -1,   8,   7,   6,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
117
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
118
	{  8,  -1,  -1,  -1,   6,  -1,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
119
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
120
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
121
	{ 13,  12,  11,  -1,   9,   8,   7,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
122
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
123
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
124
	{  9,   8,  -1,  -1,   6,  -1,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
125
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
126
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
127
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
128
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
129
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
130
	{ 12,  11,  10,  -1,   8,   7,   6,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
131
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
132
	{ 11,  -1,  -1,  -1,   9,   8,   7,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
133
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
134
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
135
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
136
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
137
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
138
	{ 12,  -1,  -1,  -1,  10,   9,   8,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
139
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
140
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
141
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
142
	{ 10,   9,   8,  -1,   6,   5,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
143
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
144
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
145
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
146
	{  9,   8,   7,  -1,   5,  -1,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
147
	{ 11,  10,   9,  -1,   7,   6,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
148
	{ 10,   9,  -1,  -1,   7,  -1,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
149
	{ 13,  12,  -1,  -1,  10,   9,   8,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
150
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
151
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
152
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
153
	{ 11,  10,   9,  -1,   7,  -1,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
154
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
155
	{  9,  -1,  -1,  -1,   7,   6,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
156
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
157
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
158
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
159
	{  8,   7,  -1,  -1,   5,   4,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
160
	{  9,   8,  -1,  -1,   6,   5,   4,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
161
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
162
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
163
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
164
	{  8,  -1,  -1,  -1,   6,   5,   4,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
165
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
166
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
167
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
168
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
169
	{  6,  -1,  -1,  -1,   4,  -1,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
170
	{ 10,   9,   8,  -1,   6,   5,   4,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
171
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
172
	{ 10,  -1,  -1,  -1,   8,   7,   6,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
173
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
174
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
175
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
176
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
177
	{ 11,  10,  -1,  -1,   8,   7,   6,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
178
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
179
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
180
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
181
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
182
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
183
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
184
	{ 11,  10,   9,  -1,   7,   6,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
185
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
186
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
187
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
188
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
189
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
190
	{  8,  -1,  -1,  -1,   6,  -1,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
191
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
192
	{ 10,   9,   8,  -1,   6,  -1,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
193
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
194
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
195
	{ 12,  11,  10,  -1,   8,   7,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
196
	{ 11,  10,  -1,  -1,   8,  -1,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
197
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
198
	{ 11,  10,  -1,  -1,   8,   7,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
199
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
200
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
201
	{  8,   7,  -1,  -1,   5,  -1,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
202
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
203
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
204
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
205
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
206
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
207
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
208
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
209
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
210
	{ 10,  -1,  -1,  -1,   8,   7,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
211
	{  7,   6,  -1,  -1,   4,  -1,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
212
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
213
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
214
	{ 10,   9,  -1,  -1,   7,   6,   5,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
215
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
216
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
217
	{ 10,   9,  -1,  -1,   7,   6,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
218
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
219
	{  9,   8,  -1,  -1,   6,   5,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
220
	{ 10,   9,  -1,  -1,   7,   6,   5,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
221
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
222
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
223
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
224
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
225
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
226
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
227
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
228
	{  9,  -1,  -1,  -1,   7,   6,   5,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
229
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
230
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
231
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
232
	{ 11,  10,   9,  -1,   7,  -1,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
233
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
234
	{  8,  -1,  -1,  -1,   6,   5,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
235
	{ 11,  10,   9,  -1,   7,   6,   5,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
236
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
237
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
238
	{  9,  -1,  -1,  -1,   7,   6,   5,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
239
	{  7,  -1,  -1,  -1,   5,  -1,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
240
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
241
	{ 11,  10,   9,  -1,   7,   6,   5,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
242
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
243
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
244
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
245
	{ 11,  -1,  -1,  -1,   9,   8,   7,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
246
	{ 10,   9,  -1,  -1,   7,  -1,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
247
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
248
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
249
	{  8,   7,   6,  -1,   4,  -1,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
250
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
251
	{  9,   8,   7,  -1,   5,   4,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
252
	{ 10,   9,   8,  -1,   6,  -1,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
253
	{  8,  -1,  -1,  -1,   6,   5,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
254
	{ 12,  11,  -1,  -1,   9,   8,   7,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
255
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
256
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
257
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
258
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
259
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
260
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
261
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
262
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
263
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
264
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
265
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
266
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
267
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
268
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
269
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
270
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
271
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
272
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
273
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
274
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
275
	{  7,  -1,  -1,  -1,   5,  -1,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
276
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
277
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
278
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
279
	{ 10,   9,  -1,  -1,   7,   6,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
280
	{  9,  -1,  -1,  -1,   7,  -1,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
281
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
282
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
283
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
284
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
285
	{ 14,  13,  12,  -1,  10,   9,   8,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
286
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
287
	{  9,   8,  -1,  -1,   6,  -1,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
288
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
289
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
290
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
291
	{ 13,  12,  11,  -1,   9,   8,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
292
	{ 10,   9,   8,  -1,   6,  -1,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
293
	{  7,  -1,  -1,  -1,   5,   4,  -1,  -1,   2,  -1,  -1,  -1,   0,  -1,  -1,  -1},
294
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
295
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
296
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
297
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
298
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
299
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
300
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
301
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
302
	{ 11,  -1,  -1,  -1,   9,   8,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
303
	{  9,   8,  -1,  -1,   6,  -1,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
304
	{ 12,  11,  -1,  -1,   9,   8,   7,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
305
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
306
	{  9,   8,   7,  -1,   5,  -1,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
307
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
308
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
309
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
310
	{ 12,  11,  -1,  -1,   9,   8,  -1,  -1,   6,   5,   4,  -1,   2,   1,   0,  -1},
311
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
312
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
313
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
314
	{ 12,  11,  10,  -1,   8,   7,  -1,  -1,   5,   4,  -1,  -1,   2,   1,   0,  -1},
315
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
316
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
317
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
318
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
319
	{  9,   8,  -1,  -1,   6,   5,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
320
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
321
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
322
	{ 13,  12,  11,  -1,   9,   8,   7,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
323
	{  8,   7,  -1,  -1,   5,  -1,  -1,  -1,   3,  -1,  -1,  -1,   1,   0,  -1,  -1},
324
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
325
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
326
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
327
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
328
	{ 11,  10,  -1,  -1,   8,   7,   6,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
329
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
330
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
331
	{ 10,  -1,  -1,  -1,   8,   7,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
332
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
333
	{ 11,  10,   9,  -1,   7,   6,  -1,  -1,   4,   3,  -1,  -1,   1,   0,  -1,  -1},
334
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
335
	{ 11,  10,  -1,  -1,   8,   7,  -1,  -1,   5,   4,   3,  -1,   1,   0,  -1,  -1},
336
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
337
	{ 12,  11,  10,  -1,   8,   7,   6,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
338
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
339
	{ 10,   9,  -1,  -1,   7,   6,  -1,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
340
	{ 11,  10,  -1,  -1,   8,   7,   6,  -1,   4,  -1,  -1,  -1,   2,   1,   0,  -1},
341
	{  9,  -1,  -1,  -1,   7,   6,  -1,  -1,   4,   3,   2,  -1,   0,  -1,  -1,  -1},
342
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
343
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
344
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
345
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
346
	{ 10,   9,   8,  -1,   6,   5,  -1,  -1,   3,   2,  -1,  -1,   0,  -1,  -1,  -1},
347
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
348
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
349
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
350
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
351
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
352
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
353
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
354
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
355
	{ -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
356
};
357
358
inline unsigned perfecthash(unsigned v){
359
	/* DEEP MAGIC BEGINS HERE. */
360
	return (unsigned)_mm_crc32_u32(0,v*0x000020de)>>24;
361
}
362
363
inline UINT32 MyGetIP_comp(const char *str) {
364
  __m128i input = _mm_lddqu_si128((const __m128i*)str);   //"192.167.1.3"
365
  uint64_t zm = _mm_movemask_epi8(_mm_cmpeq_epi8(input, _mm_setzero_si128()));
366
  zm ^= (zm-1);                                           //(1<<12) - 1
367
  input = _mm_sub_epi8(input, _mm_set1_epi8('0'));        //1 9 2 254 1 6 7 254 1 254 3 208 245 0 8 40
368
  __m128i cmp = input;                                    //...X...X.X.XX...  (signs)
369
  uint64_t mask = _mm_movemask_epi8(cmp);                 //6792 - magic index
370
  mask &= zm;
371
  uint64_t hashmask = perfecthash(mask);
372
  __m128i shuf = ((const __m128i*)TBL)[hashmask];         //10 -1 -1 -1 8 -1 -1 -1 6 5 4 -1 2 1 0 -1 
373
  __m128i arr = _mm_shuffle_epi8(input, shuf);            //3 0 0 0 | 1 0 0 0 | 7 6 1 0 | 2 9 1 0 
374
  __m128i coeffs = _mm_set_epi8(0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1, 0, 100, 10, 1);
375
  __m128i prod = _mm_maddubs_epi16(coeffs, arr);          //3 0 | 1 0 | 67 100 | 92 100 
376
  prod = _mm_hadd_epi16(prod, prod);                      //3 | 1 | 167 | 192 | ? | ? | ? | ?
377
  __m128i imm = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 4, 2, 0);
378
  prod = _mm_shuffle_epi8(prod, imm);                     //3 1 167 192 0 0 0 0 0 0 0 0 0 0 0 0
379
  return _mm_extract_epi32(prod, 0);
380
}
381
382
//========================================== TESTING =================================================
383
384
static const int CNT = 16<<10;
385
386
int main() {
387
  MyInit();
388
  printf("%08X\n", MyGetIP("192.167.1.3"));
389
390
  std::vector<std::string> samples;
391
  for (int i = 0; i < CNT; i++) {
392
    std::string str;
393
    for (int j = 0; j < 4; j++) {
394
      if (j) str += '.';
395
      int x = rand() % 256;
396
      char qq[16];
397
      sprintf(qq, "%d", x);
398
      str += qq;
399
    }
400
    samples.push_back(str);
401
402
//    printf("%s\n", samples[i].c_str());
403
	auto a = GetIP(samples.back().c_str());
404
	auto b = MyGetIP(samples.back().c_str());
405
  auto c = MyGetIP_comp(samples.back().c_str());
406
	if (a != b || a != c || b != c)
407
      printf("%s: %08X vs %08X vs %08X\n", samples[i].c_str(), a, b, c);
408
		
409
  }
410
411
412
{
413
  int start = clock();
414
  int sum = 0;
415
  for (int i = 0; i < 1<<27; i++) {
416
      const char *input = samples[(i+0) & (CNT-1)].c_str();
417
      sum += MyGetIP(input);
418
  }
419
  int elapsed = clock() - start;
420
  printf("Time = %0.3lf   (%d)\n", double(elapsed) / CLOCKS_PER_SEC, sum);
421
}
422
{
423
  int start = clock();
424
  int sum = 0;
425
  for (int i = 0; i < 1<<27; i++) {
426
      const char *input = samples[(i+0) & (CNT-1)].c_str();
427
      sum += MyGetIP_comp(input);
428
  }
429
  int elapsed = clock() - start;
430
  printf("Time = %0.3lf   (%d)\n", double(elapsed) / CLOCKS_PER_SEC, sum);
431
}
432
{
433
  int start = clock();
434
  int sum = 0;
435
  for (int i = 0; i < 1<<27; i++) {
436
      const char *input = samples[i & (CNT-1)].c_str();
437
      sum += GetIP(input);
438
  }
439
  int elapsed = clock() - start;
440
  printf("Time = %0.3lf   (%d)\n", double(elapsed) / CLOCKS_PER_SEC, sum);
441
}
442
443
  return 0;
444
}