1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
3 | #ident "$Id$" |
4 | /*====== |
5 | This file is part of PerconaFT. |
6 | |
7 | |
8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
9 | |
10 | PerconaFT is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU General Public License, version 2, |
12 | as published by the Free Software Foundation. |
13 | |
14 | PerconaFT is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
21 | |
22 | ---------------------------------------- |
23 | |
24 | PerconaFT is free software: you can redistribute it and/or modify |
25 | it under the terms of the GNU Affero General Public License, version 3, |
26 | as published by the Free Software Foundation. |
27 | |
28 | PerconaFT is distributed in the hope that it will be useful, |
29 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | GNU Affero General Public License for more details. |
32 | |
33 | You should have received a copy of the GNU Affero General Public License |
34 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
35 | ======= */ |
36 | |
37 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
38 | |
39 | #include <toku_stdlib.h> |
40 | #include <portability/toku_portability.h> |
41 | |
42 | #include "x1764.h" |
43 | |
44 | #define PRINT 0 |
45 | |
46 | uint32_t toku_x1764_memory_simple (const void *buf, int len) |
47 | { |
48 | const uint64_t *CAST_FROM_VOIDP(lbuf, buf); |
49 | uint64_t c=0; |
50 | while (len>=8) { |
51 | c = c*17 + *lbuf; |
52 | if (PRINT) printf("%d: c=%016" PRIx64 " sum=%016" PRIx64 "\n" , __LINE__, *lbuf, c); |
53 | lbuf++; |
54 | len-=8; |
55 | } |
56 | if (len>0) { |
57 | const uint8_t *cbuf=(uint8_t*)lbuf; |
58 | int i; |
59 | uint64_t input=0; |
60 | for (i=0; i<len; i++) { |
61 | input |= ((uint64_t)(cbuf[i]))<<(8*i); |
62 | } |
63 | c = c*17 + input; |
64 | } |
65 | return ~((c&0xFFFFFFFF) ^ (c>>32)); |
66 | } |
67 | |
68 | uint32_t toku_x1764_memory (const void *vbuf, int len) |
69 | { |
70 | const uint8_t *CAST_FROM_VOIDP(buf, vbuf); |
71 | int len_4_words = 4*sizeof(uint64_t); |
72 | uint64_t suma=0, sumb=0, sumc=0, sumd=0; |
73 | while (len >= len_4_words) { |
74 | suma = suma*(17LL*17LL*17LL*17LL) + *(uint64_t*)(buf +0*sizeof(uint64_t)); |
75 | sumb = sumb*(17LL*17LL*17LL*17LL) + *(uint64_t*)(buf +1*sizeof(uint64_t)); |
76 | sumc = sumc*(17LL*17LL*17LL*17LL) + *(uint64_t*)(buf +2*sizeof(uint64_t)); |
77 | sumd = sumd*(17LL*17LL*17LL*17LL) + *(uint64_t*)(buf +3*sizeof(uint64_t)); |
78 | buf += len_4_words; |
79 | len -= len_4_words; |
80 | } |
81 | uint64_t sum = suma*17L*17L*17L + sumb*17L*17L + sumc*17L + sumd; |
82 | assert(len>=0); |
83 | while ((uint64_t)len>=sizeof(uint64_t)) { |
84 | sum = sum*17 + *(uint64_t*)buf; |
85 | buf+=sizeof(uint64_t); |
86 | len-=sizeof(uint64_t); |
87 | } |
88 | if (len>0) { |
89 | uint64_t tailsum = 0; |
90 | for (int i=0; i<len; i++) { |
91 | tailsum |= ((uint64_t)(buf[i]))<<(8*i); |
92 | } |
93 | sum = sum*17 + tailsum; |
94 | } |
95 | return ~((sum&0xFFFFFFFF) ^ (sum>>32)); |
96 | } |
97 | |
98 | |
99 | void toku_x1764_init(struct x1764 *l) { |
100 | l->sum=0; |
101 | l->input=0; |
102 | l->n_input_bytes=0; |
103 | } |
104 | |
105 | void toku_x1764_add (struct x1764 *l, const void *vbuf, int len) { |
106 | if (PRINT) printf("%d: n_input_bytes=%d len=%d\n" , __LINE__, l->n_input_bytes, len); |
107 | int n_input_bytes = l->n_input_bytes; |
108 | const unsigned char *CAST_FROM_VOIDP(cbuf, vbuf); |
109 | // Special case short inputs |
110 | if (len==1) { |
111 | uint64_t input = l->input | ((uint64_t)(*cbuf))<<(8*n_input_bytes); |
112 | n_input_bytes++; |
113 | if (n_input_bytes==8) { |
114 | l->sum = l->sum*17 + input; |
115 | l->n_input_bytes = 0; |
116 | l->input = 0; |
117 | } else { |
118 | l->input = input; |
119 | l->n_input_bytes = n_input_bytes; |
120 | } |
121 | return; |
122 | } else if (len==2) { |
123 | uint64_t input = l->input; |
124 | uint64_t thisv = ((uint64_t)(*(uint16_t*)cbuf)); |
125 | if (n_input_bytes==7) { |
126 | l->sum = l->sum*17 + (input | (thisv<<(8*7))); |
127 | l->input = thisv>>8; |
128 | l->n_input_bytes = 1; |
129 | } else if (n_input_bytes==6) { |
130 | l->sum = l->sum*17 + (input | (thisv<<(8*6))); |
131 | l->input = 0; |
132 | l->n_input_bytes = 0; |
133 | } else { |
134 | l->input = input | (thisv<<(8*n_input_bytes)); |
135 | l->n_input_bytes += 2; |
136 | } |
137 | return; |
138 | } |
139 | |
140 | uint64_t sum; |
141 | //assert(len>=0); |
142 | if (n_input_bytes) { |
143 | uint64_t input = l->input; |
144 | if (len>=8) { |
145 | sum = l->sum; |
146 | while (len>=8) { |
147 | uint64_t thisv = *(uint64_t*)cbuf; |
148 | input |= thisv<<(8*n_input_bytes); |
149 | sum = sum*17 + input; |
150 | if (PRINT) printf("%d: input=%016" PRIx64 " sum=%016" PRIx64 "\n" , __LINE__, input, sum); |
151 | input = thisv>>(8*(8-n_input_bytes)); |
152 | if (PRINT) printf("%d: input=%016" PRIx64 "\n" , __LINE__, input); |
153 | len-=8; |
154 | cbuf+=8; |
155 | // n_input_bytes remains unchanged |
156 | if (PRINT) printf("%d: n_input_bytes=%d len=%d\n" , __LINE__, l->n_input_bytes, len); |
157 | } |
158 | l->sum = sum; |
159 | } |
160 | if (len>=4) { |
161 | uint64_t thisv = *(uint32_t*)cbuf; |
162 | if (n_input_bytes<4) { |
163 | input |= thisv<<(8*n_input_bytes); |
164 | if (PRINT) printf("%d: input=%016" PRIx64 "\n" , __LINE__, input); |
165 | n_input_bytes+=4; |
166 | } else { |
167 | input |= thisv<<(8*n_input_bytes); |
168 | l->sum = l->sum*17 + input; |
169 | if (PRINT) printf("%d: input=%016" PRIx64 " sum=%016" PRIx64 "\n" , __LINE__, input, l->sum); |
170 | input = thisv>>(8*(8-n_input_bytes)); |
171 | n_input_bytes-=4; |
172 | if (PRINT) printf("%d: input=%016" PRIx64 " n_input_bytes=%d\n" , __LINE__, input, n_input_bytes); |
173 | } |
174 | len-=4; |
175 | cbuf+=4; |
176 | if (PRINT) printf("%d: len=%d\n" , __LINE__, len); |
177 | } |
178 | //assert(n_input_bytes<=8); |
179 | while (n_input_bytes<8 && len) { |
180 | input |= ((uint64_t)(*cbuf))<<(8*n_input_bytes); |
181 | n_input_bytes++; |
182 | cbuf++; |
183 | len--; |
184 | } |
185 | //assert(len>=0); |
186 | if (n_input_bytes<8) { |
187 | //assert(len==0); |
188 | l->input = input; |
189 | l->n_input_bytes = n_input_bytes; |
190 | if (PRINT) printf("%d: n_input_bytes=%d\n" , __LINE__, l->n_input_bytes); |
191 | return; |
192 | } |
193 | sum = l->sum*17 + input; |
194 | } else { |
195 | //assert(len>=0); |
196 | sum = l->sum; |
197 | } |
198 | //assert(len>=0); |
199 | while (len>=8) { |
200 | sum = sum*17 + *(uint64_t*)cbuf; |
201 | cbuf+=8; |
202 | len -=8; |
203 | } |
204 | l->sum = sum; |
205 | n_input_bytes = 0; |
206 | uint64_t input; |
207 | l->n_input_bytes = len; |
208 | // Surprisingly, the loop is the fastest on bradley's laptop. |
209 | if (1) { |
210 | int i; |
211 | input=0; |
212 | for (i=0; i<len; i++) { |
213 | input |= ((uint64_t)(cbuf[i]))<<(8*i); |
214 | } |
215 | } else if (0) { |
216 | switch (len) { |
217 | case 7: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(uint16_t*)(cbuf+4)))<<32) | (((uint64_t)(*(cbuf+4)))<<48); break; |
218 | case 6: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(uint16_t*)(cbuf+4)))<<32); break; |
219 | case 5: input = ((uint64_t)(*(uint32_t*)(cbuf))) | (((uint64_t)(*(cbuf+4)))<<32); break; |
220 | case 4: input = ((uint64_t)(*(uint32_t*)(cbuf))); break; |
221 | case 3: input = ((uint64_t)(*(uint16_t*)(cbuf))) | (((uint64_t)(*(cbuf+2)))<<16); break; |
222 | case 2: input = ((uint64_t)(*(uint16_t*)(cbuf))); break; |
223 | case 1: input = ((uint64_t)(*cbuf)); break; |
224 | case 0: input = 0; break; |
225 | default: abort(); |
226 | } |
227 | } else { |
228 | input=0; |
229 | int i=0; |
230 | if (len>=4) { input = ((uint64_t)(*(uint32_t*)(cbuf))); cbuf+=4; len-=4; i=4;} |
231 | if (len>=2) { input |= ((uint64_t)(*(uint16_t*)(cbuf)))<<(i*8); cbuf+=2; len-=2; i+=2; } |
232 | if (len>=1) { input |= ((uint64_t)(*(uint8_t *)(cbuf)))<<(i*8); /*cbuf+=1; len-=1; i++;*/ } |
233 | } |
234 | l->input = input; |
235 | if (PRINT) printf("%d: n_input_bytes=%d\n" , __LINE__, l->n_input_bytes); |
236 | } |
237 | uint32_t toku_x1764_finish (struct x1764 *l) { |
238 | if (PRINT) printf("%d: n_input_bytes=%d\n" , __LINE__, l->n_input_bytes); |
239 | int len = l->n_input_bytes; |
240 | if (len>0) { |
241 | l->sum = l->sum*17 + l->input; |
242 | } |
243 | return ~((l->sum &0xffffffff) ^ (l->sum>>32)); |
244 | } |
245 | |