bitshares-cityhash 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 404a22d513da567915bc1b950df4655491c3adc8
4
+ data.tar.gz: 1085bc524f0ad377a3831d7eb9ac0b772c0ead83
5
+ SHA512:
6
+ metadata.gz: 668ad0fe8d25abf641b8525bb1aeb85b677923dc39d1858044776944a11318d1fa1055425c16d47a8cd4e9c1487f9f02b3a3aff7918858a389bbfecbf28814df
7
+ data.tar.gz: 9a8408bbb0f6765466977712767090f051a1844ae1ca61c97129272b21c2ec067538b4c44487d7b6504ee43f9ff44ed0a0aee16b1dbde78cc4bdaaea546fd899
@@ -0,0 +1,7 @@
1
+ *.so
2
+ *.bundle
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+ tmp/*
7
+ vendor/bundle
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ - 2.3
@@ -0,0 +1,25 @@
1
+ ## 0.9.0 (October 11, 2017) ##
2
+
3
+ ### enhancements
4
+ * update cityhash lib version
5
+ * ditch old rubies. support only Ruby 2.0+
6
+ * let the environment dictate the arch
7
+ * do not define CRC methods if it's not supported by system
8
+
9
+ ## 0.8.1 (May 18, 2013) ##
10
+
11
+ ### bugfixes
12
+ * do not segfalt with non-string input
13
+ * use proper compiler flag to compile crc version of cityhash lib (see README about installing gem on OSX,
14
+ on Linux everything should work out of the box)
15
+
16
+ ## 0.8.0 (May 5, 2013) ##
17
+
18
+ ### enhancements
19
+ * add crc methods
20
+
21
+ ## 0.7.0 (October 25, 2012) ##
22
+
23
+ ### enhancements
24
+ * add CityHash.hash32 method
25
+ * update libcityhash to 1.1. See [NEWS](http://code.google.com/p/cityhash/source/browse/trunk/NEWS)
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'rake-compiler'
7
+ gem 'minitest', '~> 4.7.3'
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 nashby
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ ### cityhash [![TravisCI](https://secure.travis-ci.org/nashby/cityhash.png?branch=master)](http://travis-ci.org/nashby/cityhash)
2
+
3
+ Ruby wrapper for google's cityhash.
4
+
5
+ ### Install
6
+
7
+ gem install cityhash
8
+
9
+ ### Usage
10
+
11
+ ```ruby
12
+ require 'cityhash'
13
+
14
+ text = "test"
15
+ seed1 = 12345
16
+ seed2 = 54321
17
+
18
+ CityHash.hash32(text) # => 1633095781
19
+ CityHash.hash64(text) # => 8581389452482819506
20
+ CityHash.hash64(text, seed1) # => 9154302171269876511
21
+ CityHash.hash64(text, seed1, seed2) # => 4854399283587686019
22
+ CityHash.hash128(text) # => 124124989950401219618153994964897029896
23
+ CityHash.hash128(text, seed1) # => 101668641288246442316643001405184598611
24
+ CityHash.hash128crc(text) # => 124124989950401219618153994964897029896
25
+ CityHash.hash128crc(text, seed1) # => 101668641288246442316643001405184598611
26
+ CityHash.hash256crc(text) # => 11964743055457135893972873789222488394617411264226841264756
27
+ ```
28
+
29
+ ### Important note
30
+
31
+ CityHash does not maintain backward compatibility with previous versions. You should not use CityHash for persitent storage, or else never upgrade it.
32
+
33
+ If you need backward compatibility please consider other hash functions like [xxHash](https://github.com/nashby/xxhash) or [MurmurHash](https://github.com/ksss/digest-murmurhash)
34
+
35
+ ### Contributing to cityhash
36
+
37
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
38
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
39
+ * Fork the project
40
+ * Start a feature/bugfix branch
41
+ * Commit and push until you are happy with your contribution
42
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
43
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
44
+
45
+ ### Authors
46
+
47
+ #### [Contributors](http://github.com/nashby/cityhash/contributors)
48
+ - [Johannes Holzfuß](http://github.com/DataWraith)
49
+ - [Quin Hoxie](https://github.com/qhoxie)
50
+ - [David Dai](https://github.com/newtonapple)
51
+ - [Sergey Nartimov](https://github.com/lest)
52
+
53
+ [Vasiliy Ermolovich](http://github.com/nashby/)<br/>
54
+
55
+ ### Copyright
56
+
57
+ Copyright (c) 2012 Vasiliy Ermolovich. See LICENSE.txt for
58
+ further details.
@@ -0,0 +1,20 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ t.pattern = 'test/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+
12
+ desc "Run tests"
13
+ task :default => :test
14
+
15
+ require 'rake/extensiontask'
16
+ Rake::ExtensionTask.new('cityhash') do |ext|
17
+ ext.lib_dir = 'lib/cityhash'
18
+ end
19
+
20
+ Rake::Task[:test].prerequisites << :compile
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cityhash/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bitshares-cityhash"
7
+ s.version = CityHash::VERSION
8
+ s.summary = 'cityhash gem for bitshares blockchain.'
9
+ s.license = 'MIT'
10
+ s.authors = ["Vasiliy Ermolovich", "syalon"]
11
+ s.email = ["younash@gmail.com", "hanomirin@foxmail.com"]
12
+ s.homepage = "https://github.com/syalon/bitshares-cityhash.git"
13
+ s.summary = %q{ruby bindings for google's cityhash}
14
+
15
+ s.rubyforge_project = "cityhash"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.extensions = ["ext/cityhash/extconf.rb"]
22
+ end
@@ -0,0 +1,645 @@
1
+ // Copyright (c) 2011 Google, Inc.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in
11
+ // all copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ // THE SOFTWARE.
20
+ //
21
+ // CityHash, by Geoff Pike and Jyrki Alakuijala
22
+ //
23
+ // This file provides CityHash64() and related functions.
24
+ //
25
+ // It's probably possible to create even faster hash functions by
26
+ // writing a program that systematically explores some of the space of
27
+ // possible hash functions, by using SIMD instructions, or by
28
+ // compromising on hash quality.
29
+
30
+ #include <city.h>
31
+
32
+ #include <algorithm>
33
+ #include <string.h> // for memcpy and memset
34
+
35
+ using namespace std;
36
+
37
+ static uint64 UNALIGNED_LOAD64(const char *p) {
38
+ uint64 result;
39
+ memcpy(&result, p, sizeof(result));
40
+ return result;
41
+ }
42
+
43
+ static uint32 UNALIGNED_LOAD32(const char *p) {
44
+ uint32 result;
45
+ memcpy(&result, p, sizeof(result));
46
+ return result;
47
+ }
48
+
49
+ #ifdef _MSC_VER
50
+
51
+ #include <stdlib.h>
52
+ #define bswap_32(x) _byteswap_ulong(x)
53
+ #define bswap_64(x) _byteswap_uint64(x)
54
+
55
+ #elif defined(__APPLE__)
56
+
57
+ // Mac OS X / Darwin features
58
+ #include <libkern/OSByteOrder.h>
59
+ #define bswap_32(x) OSSwapInt32(x)
60
+ #define bswap_64(x) OSSwapInt64(x)
61
+
62
+ #elif defined(__sun) || defined(sun)
63
+
64
+ #include <sys/byteorder.h>
65
+ #define bswap_32(x) BSWAP_32(x)
66
+ #define bswap_64(x) BSWAP_64(x)
67
+
68
+ #elif defined(__FreeBSD__)
69
+
70
+ #include <sys/endian.h>
71
+ #define bswap_32(x) bswap32(x)
72
+ #define bswap_64(x) bswap64(x)
73
+
74
+ #elif defined(__OpenBSD__)
75
+
76
+ #include <sys/types.h>
77
+ #define bswap_32(x) swap32(x)
78
+ #define bswap_64(x) swap64(x)
79
+
80
+ #elif defined(__NetBSD__)
81
+
82
+ #include <sys/types.h>
83
+ #include <machine/bswap.h>
84
+ #if defined(__BSWAP_RENAME) && !defined(__bswap_32)
85
+ #define bswap_32(x) bswap32(x)
86
+ #define bswap_64(x) bswap64(x)
87
+ #endif
88
+
89
+ #else
90
+
91
+ #include <byteswap.h>
92
+
93
+ #endif
94
+
95
+ #ifdef WORDS_BIGENDIAN
96
+ #define uint32_in_expected_order(x) (bswap_32(x))
97
+ #define uint64_in_expected_order(x) (bswap_64(x))
98
+ #else
99
+ #define uint32_in_expected_order(x) (x)
100
+ #define uint64_in_expected_order(x) (x)
101
+ #endif
102
+
103
+ #if !defined(LIKELY)
104
+ #if HAVE_BUILTIN_EXPECT
105
+ #define LIKELY(x) (__builtin_expect(!!(x), 1))
106
+ #else
107
+ #define LIKELY(x) (x)
108
+ #endif
109
+ #endif
110
+
111
+ static uint64 Fetch64(const char *p) {
112
+ return uint64_in_expected_order(UNALIGNED_LOAD64(p));
113
+ }
114
+
115
+ static uint32 Fetch32(const char *p) {
116
+ return uint32_in_expected_order(UNALIGNED_LOAD32(p));
117
+ }
118
+
119
+ // Some primes between 2^63 and 2^64 for various uses.
120
+ static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
121
+ static const uint64 k1 = 0xb492b66fbe98f273ULL;
122
+ static const uint64 k2 = 0x9ae16a3b2f90404fULL;
123
+
124
+ // Magic numbers for 32-bit hashing. Copied from Murmur3.
125
+ static const uint32 c1 = 0xcc9e2d51;
126
+ static const uint32 c2 = 0x1b873593;
127
+
128
+ // A 32-bit to 32-bit integer hash copied from Murmur3.
129
+ static uint32 fmix(uint32 h)
130
+ {
131
+ h ^= h >> 16;
132
+ h *= 0x85ebca6b;
133
+ h ^= h >> 13;
134
+ h *= 0xc2b2ae35;
135
+ h ^= h >> 16;
136
+ return h;
137
+ }
138
+
139
+ static uint32 Rotate32(uint32 val, int shift) {
140
+ // Avoid shifting by 32: doing so yields an undefined result.
141
+ return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
142
+ }
143
+
144
+ #undef PERMUTE3
145
+ #define PERMUTE3(a, b, c) do { std::swap(a, b); std::swap(a, c); } while (0)
146
+
147
+ static uint32 Mur(uint32 a, uint32 h) {
148
+ // Helper from Murmur3 for combining two 32-bit values.
149
+ a *= c1;
150
+ a = Rotate32(a, 17);
151
+ a *= c2;
152
+ h ^= a;
153
+ h = Rotate32(h, 19);
154
+ return h * 5 + 0xe6546b64;
155
+ }
156
+
157
+ static uint32 Hash32Len13to24(const char *s, size_t len) {
158
+ uint32 a = Fetch32(s - 4 + (len >> 1));
159
+ uint32 b = Fetch32(s + 4);
160
+ uint32 c = Fetch32(s + len - 8);
161
+ uint32 d = Fetch32(s + (len >> 1));
162
+ uint32 e = Fetch32(s);
163
+ uint32 f = Fetch32(s + len - 4);
164
+ uint32 h = len;
165
+
166
+ return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
167
+ }
168
+
169
+ static uint32 Hash32Len0to4(const char *s, size_t len) {
170
+ uint32 b = 0;
171
+ uint32 c = 9;
172
+ for (size_t i = 0; i < len; i++) {
173
+ signed char v = s[i];
174
+ b = b * c1 + v;
175
+ c ^= b;
176
+ }
177
+ return fmix(Mur(b, Mur(len, c)));
178
+ }
179
+
180
+ static uint32 Hash32Len5to12(const char *s, size_t len) {
181
+ uint32 a = len, b = len * 5, c = 9, d = b;
182
+ a += Fetch32(s);
183
+ b += Fetch32(s + len - 4);
184
+ c += Fetch32(s + ((len >> 1) & 4));
185
+ return fmix(Mur(c, Mur(b, Mur(a, d))));
186
+ }
187
+
188
+ uint32 CityHash32(const char *s, size_t len) {
189
+ if (len <= 24) {
190
+ return len <= 12 ?
191
+ (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) :
192
+ Hash32Len13to24(s, len);
193
+ }
194
+
195
+ // len > 24
196
+ uint32 h = len, g = c1 * len, f = g;
197
+ uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
198
+ uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
199
+ uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2;
200
+ uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2;
201
+ uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2;
202
+ h ^= a0;
203
+ h = Rotate32(h, 19);
204
+ h = h * 5 + 0xe6546b64;
205
+ h ^= a2;
206
+ h = Rotate32(h, 19);
207
+ h = h * 5 + 0xe6546b64;
208
+ g ^= a1;
209
+ g = Rotate32(g, 19);
210
+ g = g * 5 + 0xe6546b64;
211
+ g ^= a3;
212
+ g = Rotate32(g, 19);
213
+ g = g * 5 + 0xe6546b64;
214
+ f += a4;
215
+ f = Rotate32(f, 19);
216
+ f = f * 5 + 0xe6546b64;
217
+ size_t iters = (len - 1) / 20;
218
+ do {
219
+ uint32 a0 = Rotate32(Fetch32(s) * c1, 17) * c2;
220
+ uint32 a1 = Fetch32(s + 4);
221
+ uint32 a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
222
+ uint32 a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
223
+ uint32 a4 = Fetch32(s + 16);
224
+ h ^= a0;
225
+ h = Rotate32(h, 18);
226
+ h = h * 5 + 0xe6546b64;
227
+ f += a1;
228
+ f = Rotate32(f, 19);
229
+ f = f * c1;
230
+ g += a2;
231
+ g = Rotate32(g, 18);
232
+ g = g * 5 + 0xe6546b64;
233
+ h ^= a3 + a1;
234
+ h = Rotate32(h, 19);
235
+ h = h * 5 + 0xe6546b64;
236
+ g ^= a4;
237
+ g = bswap_32(g) * 5;
238
+ h += a4 * 5;
239
+ h = bswap_32(h);
240
+ f += a0;
241
+ PERMUTE3(f, h, g);
242
+ s += 20;
243
+ } while (--iters != 0);
244
+ g = Rotate32(g, 11) * c1;
245
+ g = Rotate32(g, 17) * c1;
246
+ f = Rotate32(f, 11) * c1;
247
+ f = Rotate32(f, 17) * c1;
248
+ h = Rotate32(h + g, 19);
249
+ h = h * 5 + 0xe6546b64;
250
+ h = Rotate32(h, 17) * c1;
251
+ h = Rotate32(h + f, 19);
252
+ h = h * 5 + 0xe6546b64;
253
+ h = Rotate32(h, 17) * c1;
254
+ return h;
255
+ }
256
+
257
+ // Bitwise right rotate. Normally this will compile to a single
258
+ // instruction, especially if the shift is a manifest constant.
259
+ static uint64 Rotate(uint64 val, int shift) {
260
+ // Avoid shifting by 64: doing so yields an undefined result.
261
+ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
262
+ }
263
+
264
+ static uint64 ShiftMix(uint64 val) {
265
+ return val ^ (val >> 47);
266
+ }
267
+
268
+ static uint64 HashLen16(uint64 u, uint64 v) {
269
+ return Hash128to64(uint128(u, v));
270
+ }
271
+
272
+ static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
273
+ // Murmur-inspired hashing.
274
+ uint64 a = (u ^ v) * mul;
275
+ a ^= (a >> 47);
276
+ uint64 b = (v ^ a) * mul;
277
+ b ^= (b >> 47);
278
+ b *= mul;
279
+ return b;
280
+ }
281
+
282
+ static uint64 HashLen0to16(const char *s, size_t len) {
283
+ if (len >= 8) {
284
+ uint64 mul = k2 + len * 2;
285
+ uint64 a = Fetch64(s) + k2;
286
+ uint64 b = Fetch64(s + len - 8);
287
+ uint64 c = Rotate(b, 37) * mul + a;
288
+ uint64 d = (Rotate(a, 25) + b) * mul;
289
+ return HashLen16(c, d, mul);
290
+ }
291
+ if (len >= 4) {
292
+ uint64 mul = k2 + len * 2;
293
+ uint64 a = Fetch32(s);
294
+ return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
295
+ }
296
+ if (len > 0) {
297
+ uint8 a = s[0];
298
+ uint8 b = s[len >> 1];
299
+ uint8 c = s[len - 1];
300
+ uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
301
+ uint32 z = len + (static_cast<uint32>(c) << 2);
302
+ return ShiftMix(y * k2 ^ z * k0) * k2;
303
+ }
304
+ return k2;
305
+ }
306
+
307
+ // This probably works well for 16-byte strings as well, but it may be overkill
308
+ // in that case.
309
+ static uint64 HashLen17to32(const char *s, size_t len) {
310
+ uint64 mul = k2 + len * 2;
311
+ uint64 a = Fetch64(s) * k1;
312
+ uint64 b = Fetch64(s + 8);
313
+ uint64 c = Fetch64(s + len - 8) * mul;
314
+ uint64 d = Fetch64(s + len - 16) * k2;
315
+ return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d,
316
+ a + Rotate(b + k2, 18) + c, mul);
317
+ }
318
+
319
+ // Return a 16-byte hash for 48 bytes. Quick and dirty.
320
+ // Callers do best to use "random-looking" values for a and b.
321
+ static pair<uint64, uint64> WeakHashLen32WithSeeds(
322
+ uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) {
323
+ a += w;
324
+ b = Rotate(b + a + z, 21);
325
+ uint64 c = a;
326
+ a += x;
327
+ a += y;
328
+ b += Rotate(a, 44);
329
+ return make_pair(a + z, b + c);
330
+ }
331
+
332
+ // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
333
+ static pair<uint64, uint64> WeakHashLen32WithSeeds(
334
+ const char* s, uint64 a, uint64 b) {
335
+ return WeakHashLen32WithSeeds(Fetch64(s),
336
+ Fetch64(s + 8),
337
+ Fetch64(s + 16),
338
+ Fetch64(s + 24),
339
+ a,
340
+ b);
341
+ }
342
+
343
+ // Return an 8-byte hash for 33 to 64 bytes.
344
+ static uint64 HashLen33to64(const char *s, size_t len) {
345
+ uint64 mul = k2 + len * 2;
346
+ uint64 a = Fetch64(s) * k2;
347
+ uint64 b = Fetch64(s + 8);
348
+ uint64 c = Fetch64(s + len - 24);
349
+ uint64 d = Fetch64(s + len - 32);
350
+ uint64 e = Fetch64(s + 16) * k2;
351
+ uint64 f = Fetch64(s + 24) * 9;
352
+ uint64 g = Fetch64(s + len - 8);
353
+ uint64 h = Fetch64(s + len - 16) * mul;
354
+ uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
355
+ uint64 v = ((a + g) ^ d) + f + 1;
356
+ uint64 w = bswap_64((u + v) * mul) + h;
357
+ uint64 x = Rotate(e + f, 42) + c;
358
+ uint64 y = (bswap_64((v + w) * mul) + g) * mul;
359
+ uint64 z = e + f + c;
360
+ a = bswap_64((x + z) * mul + y) + b;
361
+ b = ShiftMix((z + a) * mul + d + h) * mul;
362
+ return b + x;
363
+ }
364
+
365
+ uint64 CityHash64(const char *s, size_t len) {
366
+ if (len <= 32) {
367
+ if (len <= 16) {
368
+ return HashLen0to16(s, len);
369
+ } else {
370
+ return HashLen17to32(s, len);
371
+ }
372
+ } else if (len <= 64) {
373
+ return HashLen33to64(s, len);
374
+ }
375
+
376
+ // For strings over 64 bytes we hash the end first, and then as we
377
+ // loop we keep 56 bytes of state: v, w, x, y, and z.
378
+ uint64 x = Fetch64(s + len - 40);
379
+ uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
380
+ uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
381
+ pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
382
+ pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
383
+ x = x * k1 + Fetch64(s);
384
+
385
+ // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
386
+ len = (len - 1) & ~static_cast<size_t>(63);
387
+ do {
388
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
389
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
390
+ x ^= w.second;
391
+ y += v.first + Fetch64(s + 40);
392
+ z = Rotate(z + w.first, 33) * k1;
393
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
394
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
395
+ std::swap(z, x);
396
+ s += 64;
397
+ len -= 64;
398
+ } while (len != 0);
399
+ return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
400
+ HashLen16(v.second, w.second) + x);
401
+ }
402
+
403
+ uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) {
404
+ return CityHash64WithSeeds(s, len, k2, seed);
405
+ }
406
+
407
+ uint64 CityHash64WithSeeds(const char *s, size_t len,
408
+ uint64 seed0, uint64 seed1) {
409
+ return HashLen16(CityHash64(s, len) - seed0, seed1);
410
+ }
411
+
412
+ // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
413
+ // of any length representable in signed long. Based on City and Murmur.
414
+ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
415
+ uint64 a = Uint128Low64(seed);
416
+ uint64 b = Uint128High64(seed);
417
+ uint64 c = 0;
418
+ uint64 d = 0;
419
+ signed long l = len - 16;
420
+ if (l <= 0) { // len <= 16
421
+ a = ShiftMix(a * k1) * k1;
422
+ c = b * k1 + HashLen0to16(s, len);
423
+ d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
424
+ } else { // len > 16
425
+ c = HashLen16(Fetch64(s + len - 8) + k1, a);
426
+ d = HashLen16(b + len, c + Fetch64(s + len - 16));
427
+ a += d;
428
+ do {
429
+ a ^= ShiftMix(Fetch64(s) * k1) * k1;
430
+ a *= k1;
431
+ b ^= a;
432
+ c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
433
+ c *= k1;
434
+ d ^= c;
435
+ s += 16;
436
+ l -= 16;
437
+ } while (l > 0);
438
+ }
439
+ a = HashLen16(a, c);
440
+ b = HashLen16(d, b);
441
+ return uint128(a ^ b, HashLen16(b, a));
442
+ }
443
+
444
+ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
445
+ if (len < 128) {
446
+ return CityMurmur(s, len, seed);
447
+ }
448
+
449
+ // We expect len >= 128 to be the common case. Keep 56 bytes of state:
450
+ // v, w, x, y, and z.
451
+ pair<uint64, uint64> v, w;
452
+ uint64 x = Uint128Low64(seed);
453
+ uint64 y = Uint128High64(seed);
454
+ uint64 z = len * k1;
455
+ v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
456
+ v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
457
+ w.first = Rotate(y + z, 35) * k1 + x;
458
+ w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
459
+
460
+ // This is the same inner loop as CityHash64(), manually unrolled.
461
+ do {
462
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
463
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
464
+ x ^= w.second;
465
+ y += v.first + Fetch64(s + 40);
466
+ z = Rotate(z + w.first, 33) * k1;
467
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
468
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
469
+ std::swap(z, x);
470
+ s += 64;
471
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
472
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
473
+ x ^= w.second;
474
+ y += v.first + Fetch64(s + 40);
475
+ z = Rotate(z + w.first, 33) * k1;
476
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
477
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
478
+ std::swap(z, x);
479
+ s += 64;
480
+ len -= 128;
481
+ } while (LIKELY(len >= 128));
482
+ x += Rotate(v.first + z, 49) * k0;
483
+ y = y * k0 + Rotate(w.second, 37);
484
+ z = z * k0 + Rotate(w.first, 27);
485
+ w.first *= 9;
486
+ v.first *= k0;
487
+ // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
488
+ for (size_t tail_done = 0; tail_done < len; ) {
489
+ tail_done += 32;
490
+ y = Rotate(x + y, 42) * k0 + v.second;
491
+ w.first += Fetch64(s + len - tail_done + 16);
492
+ x = x * k0 + w.first;
493
+ z += w.second + Fetch64(s + len - tail_done);
494
+ w.second += v.first;
495
+ v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
496
+ v.first *= k0;
497
+ }
498
+ // At this point our 56 bytes of state should contain more than
499
+ // enough information for a strong 128-bit hash. We use two
500
+ // different 56-byte-to-8-byte hashes to get a 16-byte final result.
501
+ x = HashLen16(x, v.first);
502
+ y = HashLen16(y + z, w.first);
503
+ return uint128(HashLen16(x + v.second, w.second) + y,
504
+ HashLen16(x + w.second, y + v.second));
505
+ }
506
+
507
+ uint128 CityHash128(const char *s, size_t len) {
508
+ return len >= 16 ?
509
+ CityHash128WithSeed(s + 16, len - 16,
510
+ uint128(Fetch64(s), Fetch64(s + 8) + k0)) :
511
+ CityHash128WithSeed(s, len, uint128(k0, k1));
512
+ }
513
+
514
+ #ifdef __SSE4_2__
515
+ #include <citycrc.h>
516
+ #include <nmmintrin.h>
517
+
518
+ // Requires len >= 240.
519
+ static void CityHashCrc256Long(const char *s, size_t len,
520
+ uint32 seed, uint64 *result) {
521
+ uint64 a = Fetch64(s + 56) + k0;
522
+ uint64 b = Fetch64(s + 96) + k0;
523
+ uint64 c = result[0] = HashLen16(b, len);
524
+ uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
525
+ uint64 e = Fetch64(s + 184) + seed;
526
+ uint64 f = 0;
527
+ uint64 g = 0;
528
+ uint64 h = c + d;
529
+ uint64 x = seed;
530
+ uint64 y = 0;
531
+ uint64 z = 0;
532
+
533
+ // 240 bytes of input per iter.
534
+ size_t iters = len / 240;
535
+ len -= iters * 240;
536
+ do {
537
+ #undef CHUNK
538
+ #define CHUNK(r) \
539
+ PERMUTE3(x, z, y); \
540
+ b += Fetch64(s); \
541
+ c += Fetch64(s + 8); \
542
+ d += Fetch64(s + 16); \
543
+ e += Fetch64(s + 24); \
544
+ f += Fetch64(s + 32); \
545
+ a += b; \
546
+ h += f; \
547
+ b += c; \
548
+ f += d; \
549
+ g += e; \
550
+ e += z; \
551
+ g += x; \
552
+ z = _mm_crc32_u64(z, b + g); \
553
+ y = _mm_crc32_u64(y, e + h); \
554
+ x = _mm_crc32_u64(x, f + a); \
555
+ e = Rotate(e, r); \
556
+ c += e; \
557
+ s += 40
558
+
559
+ CHUNK(0); PERMUTE3(a, h, c);
560
+ CHUNK(33); PERMUTE3(a, h, f);
561
+ CHUNK(0); PERMUTE3(b, h, f);
562
+ CHUNK(42); PERMUTE3(b, h, d);
563
+ CHUNK(0); PERMUTE3(b, h, e);
564
+ CHUNK(33); PERMUTE3(a, h, e);
565
+ } while (--iters > 0);
566
+
567
+ while (len >= 40) {
568
+ CHUNK(29);
569
+ e ^= Rotate(a, 20);
570
+ h += Rotate(b, 30);
571
+ g ^= Rotate(c, 40);
572
+ f += Rotate(d, 34);
573
+ PERMUTE3(c, h, g);
574
+ len -= 40;
575
+ }
576
+ if (len > 0) {
577
+ s = s + len - 40;
578
+ CHUNK(33);
579
+ e ^= Rotate(a, 43);
580
+ h += Rotate(b, 42);
581
+ g ^= Rotate(c, 41);
582
+ f += Rotate(d, 40);
583
+ }
584
+ result[0] ^= h;
585
+ result[1] ^= g;
586
+ g += h;
587
+ a = HashLen16(a, g + z);
588
+ x += y << 32;
589
+ b += x;
590
+ c = HashLen16(c, z) + h;
591
+ d = HashLen16(d, e + result[0]);
592
+ g += e;
593
+ h += HashLen16(x, f);
594
+ e = HashLen16(a, d) + g;
595
+ z = HashLen16(b, c) + a;
596
+ y = HashLen16(g, h) + c;
597
+ result[0] = e + z + y + x;
598
+ a = ShiftMix((a + y) * k0) * k0 + b;
599
+ result[1] += a + result[0];
600
+ a = ShiftMix(a * k0) * k0 + c;
601
+ result[2] = a + result[1];
602
+ a = ShiftMix((a + e) * k0) * k0;
603
+ result[3] = a + result[2];
604
+ }
605
+
606
+ // Requires len < 240.
607
+ static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) {
608
+ char buf[240];
609
+ memcpy(buf, s, len);
610
+ memset(buf + len, 0, 240 - len);
611
+ CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
612
+ }
613
+
614
+ void CityHashCrc256(const char *s, size_t len, uint64 *result) {
615
+ if (LIKELY(len >= 240)) {
616
+ CityHashCrc256Long(s, len, 0, result);
617
+ } else {
618
+ CityHashCrc256Short(s, len, result);
619
+ }
620
+ }
621
+
622
+ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
623
+ if (len <= 900) {
624
+ return CityHash128WithSeed(s, len, seed);
625
+ } else {
626
+ uint64 result[4];
627
+ CityHashCrc256(s, len, result);
628
+ uint64 u = Uint128High64(seed) + result[0];
629
+ uint64 v = Uint128Low64(seed) + result[1];
630
+ return uint128(HashLen16(u, v + result[2]),
631
+ HashLen16(Rotate(v, 32), u * k0 + result[3]));
632
+ }
633
+ }
634
+
635
+ uint128 CityHashCrc128(const char *s, size_t len) {
636
+ if (len <= 900) {
637
+ return CityHash128(s, len);
638
+ } else {
639
+ uint64 result[4];
640
+ CityHashCrc256(s, len, result);
641
+ return uint128(result[2], result[3]);
642
+ }
643
+ }
644
+
645
+ #endif
@@ -0,0 +1,114 @@
1
+ // Copyright (c) 2011 Google, Inc.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in
11
+ // all copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ // THE SOFTWARE.
20
+ //
21
+ // CityHash, by Geoff Pike and Jyrki Alakuijala
22
+ //
23
+ // http://code.google.com/p/cityhash/
24
+ //
25
+ // This file provides a few functions for hashing strings. All of them are
26
+ // high-quality functions in the sense that they pass standard tests such
27
+ // as Austin Appleby's SMHasher. They are also fast.
28
+ //
29
+ // For 64-bit x86 code, on short strings, we don't know of anything faster than
30
+ // CityHash64 that is of comparable quality. We believe our nearest competitor
31
+ // is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
32
+ // tables and most other hashing (excluding cryptography).
33
+ //
34
+ // For 64-bit x86 code, on long strings, the picture is more complicated.
35
+ // On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
36
+ // CityHashCrc128 appears to be faster than all competitors of comparable
37
+ // quality. CityHash128 is also good but not quite as fast. We believe our
38
+ // nearest competitor is Bob Jenkins' Spooky. We don't have great data for
39
+ // other 64-bit CPUs, but for long strings we know that Spooky is slightly
40
+ // faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
41
+ // Note that CityHashCrc128 is declared in citycrc.h.
42
+ //
43
+ // For 32-bit x86 code, we don't know of anything faster than CityHash32 that
44
+ // is of comparable quality. We believe our nearest competitor is Murmur3A.
45
+ // (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
46
+ //
47
+ // Functions in the CityHash family are not suitable for cryptography.
48
+ //
49
+ // Please see CityHash's README file for more details on our performance
50
+ // measurements and so on.
51
+ //
52
+ // WARNING: This code has been only lightly tested on big-endian platforms!
53
+ // It is known to work well on little-endian platforms that have a small penalty
54
+ // for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
55
+ // It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
56
+ // bug reports are welcome.
57
+ //
58
+ // By the way, for some hash functions, given strings a and b, the hash
59
+ // of a+b is easily derived from the hashes of a and b. This property
60
+ // doesn't hold for any hash functions in this file.
61
+
62
+ #ifndef CITY_HASH_H_
63
+ #define CITY_HASH_H_
64
+
65
+ #include <stdlib.h> // for size_t.
66
+ #include <stdint.h>
67
+ #include <utility>
68
+
69
+ typedef uint8_t uint8;
70
+ typedef uint32_t uint32;
71
+ typedef uint64_t uint64;
72
+ typedef std::pair<uint64, uint64> uint128;
73
+
74
+ // inline uint64 Uint128Low64(const uint128& x) { return x.first; }
75
+ // inline uint64 Uint128High64(const uint128& x) { return x.second; }
76
+ inline uint64 Uint128Low64(const uint128& x) { return x.second; }
77
+ inline uint64 Uint128High64(const uint128& x) { return x.first; }
78
+
79
+ // Hash function for a byte array.
80
+ uint64 CityHash64(const char *buf, size_t len);
81
+
82
+ // Hash function for a byte array. For convenience, a 64-bit seed is also
83
+ // hashed into the result.
84
+ uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed);
85
+
86
+ // Hash function for a byte array. For convenience, two seeds are also
87
+ // hashed into the result.
88
+ uint64 CityHash64WithSeeds(const char *buf, size_t len,
89
+ uint64 seed0, uint64 seed1);
90
+
91
+ // Hash function for a byte array.
92
+ uint128 CityHash128(const char *s, size_t len);
93
+
94
+ // Hash function for a byte array. For convenience, a 128-bit seed is also
95
+ // hashed into the result.
96
+ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
97
+
98
+ // Hash function for a byte array. Most useful in 32-bit binaries.
99
+ uint32 CityHash32(const char *buf, size_t len);
100
+
101
+ // Hash 128 input bits down to 64 bits of output.
102
+ // This is intended to be a reasonably good hash function.
103
+ inline uint64 Hash128to64(const uint128& x) {
104
+ // Murmur-inspired hashing.
105
+ const uint64 kMul = 0x9ddfea08eb382d69ULL;
106
+ uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
107
+ a ^= (a >> 47);
108
+ uint64 b = (Uint128High64(x) ^ a) * kMul;
109
+ b ^= (b >> 47);
110
+ b *= kMul;
111
+ return b;
112
+ }
113
+
114
+ #endif // CITY_HASH_H_
@@ -0,0 +1,43 @@
1
+ // Copyright (c) 2011 Google, Inc.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ // of this software and associated documentation files (the "Software"), to deal
5
+ // in the Software without restriction, including without limitation the rights
6
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ // copies of the Software, and to permit persons to whom the Software is
8
+ // furnished to do so, subject to the following conditions:
9
+ //
10
+ // The above copyright notice and this permission notice shall be included in
11
+ // all copies or substantial portions of the Software.
12
+ //
13
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ // THE SOFTWARE.
20
+ //
21
+ // CityHash, by Geoff Pike and Jyrki Alakuijala
22
+ //
23
+ // This file declares the subset of the CityHash functions that require
24
+ // _mm_crc32_u64(). See the CityHash README for details.
25
+ //
26
+ // Functions in the CityHash family are not suitable for cryptography.
27
+
28
+ #ifndef CITY_HASH_CRC_H_
29
+ #define CITY_HASH_CRC_H_
30
+
31
+ #include <city.h>
32
+
33
+ // Hash function for a byte array.
34
+ uint128 CityHashCrc128(const char *s, size_t len);
35
+
36
+ // Hash function for a byte array. For convenience, a 128-bit seed is also
37
+ // hashed into the result.
38
+ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed);
39
+
40
+ // Hash function for a byte array. Sets result[0] ... result[3].
41
+ void CityHashCrc256(const char *s, size_t len, uint64 *result);
42
+
43
+ #endif // CITY_HASH_CRC_H_
@@ -0,0 +1,92 @@
1
+ #include <ruby.h>
2
+ #include "city.h"
3
+
4
+ #ifdef __SSE4_2__
5
+ #include "citycrc.h"
6
+ #endif
7
+
8
+ // Use this typedef to make the compiler happy when
9
+ // calling rb_define_method()
10
+ typedef VALUE (ruby_method)(...);
11
+
12
+ extern "C" VALUE cityhash_hash32(VALUE mod, VALUE input)
13
+ {
14
+ return ULL2NUM(CityHash32(StringValuePtr(input), RSTRING_LEN(input)));
15
+ }
16
+
17
+ extern "C" VALUE cityhash_hash64(VALUE mod, VALUE input)
18
+ {
19
+ Check_Type(input, T_STRING);
20
+ return ULL2NUM(CityHash64(StringValuePtr(input), RSTRING_LEN(input)));
21
+ }
22
+
23
+ extern "C" VALUE cityhash_hash64_with_seed(VALUE mod, VALUE input, VALUE seed)
24
+ {
25
+ Check_Type(input, T_STRING);
26
+ return ULL2NUM(CityHash64WithSeed(StringValuePtr(input), RSTRING_LEN(input), NUM2ULL(seed)));
27
+ }
28
+
29
+ extern "C" VALUE cityhash_hash64_with_seeds(VALUE mod, VALUE input, VALUE seed1, VALUE seed2)
30
+ {
31
+ Check_Type(input, T_STRING);
32
+ return ULL2NUM(CityHash64WithSeeds(StringValuePtr(input), RSTRING_LEN(input), NUM2ULL(seed1), NUM2ULL(seed2)));
33
+ }
34
+
35
+ extern "C" VALUE cityhash_hash128(VALUE mod, VALUE input)
36
+ {
37
+ Check_Type(input, T_STRING);
38
+ uint128 hash = CityHash128(StringValuePtr(input), RSTRING_LEN(input));
39
+ return rb_str_new((char *)&hash, sizeof(hash));
40
+ }
41
+
42
+ extern "C" VALUE cityhash_hash128_with_seed(VALUE mod, VALUE input, VALUE seed_string)
43
+ {
44
+ Check_Type(input, T_STRING);
45
+ uint128 seed = *(uint128 *)StringValuePtr(seed_string);
46
+ uint128 hash = CityHash128WithSeed(StringValuePtr(input), RSTRING_LEN(input), seed);
47
+ return rb_str_new((char *)&hash, sizeof(hash));
48
+ }
49
+
50
+ #ifdef __SSE4_2__
51
+ extern "C" VALUE cityhash_hashcrc128(VALUE mod, VALUE input)
52
+ {
53
+ uint128 hash = CityHashCrc128(StringValuePtr(input), RSTRING_LEN(input));
54
+ return rb_str_new((char *)&hash, sizeof(hash));
55
+ }
56
+
57
+ extern "C" VALUE cityhash_hashcrc128_with_seed(VALUE mod, VALUE input, VALUE seed_string)
58
+ {
59
+ uint128 seed = *(uint128 *)StringValuePtr(seed_string);
60
+ uint128 hash = CityHashCrc128WithSeed(StringValuePtr(input), RSTRING_LEN(input), seed);
61
+ return rb_str_new((char *)&hash, sizeof(hash));
62
+ }
63
+
64
+ extern "C" VALUE cityhash_hashcrc256(VALUE mod, VALUE input)
65
+ {
66
+ uint64 hash[4] = {};
67
+ CityHashCrc256(StringValuePtr(input), RSTRING_LEN(input), hash);
68
+ return rb_str_new((char *)&hash, sizeof(hash));
69
+ }
70
+ #endif
71
+
72
+ extern "C" void Init_cityhash()
73
+ {
74
+ VALUE mCityHash = rb_define_module("CityHash");
75
+ VALUE mInternal = rb_define_module_under(mCityHash, "Internal");
76
+
77
+ rb_define_singleton_method(mInternal, "hash32", (ruby_method*) &cityhash_hash32, 1);
78
+
79
+ rb_define_singleton_method(mInternal, "hash64", (ruby_method*) &cityhash_hash64, 1);
80
+ rb_define_singleton_method(mInternal, "hash64_with_seed", (ruby_method*) &cityhash_hash64_with_seed, 2);
81
+ rb_define_singleton_method(mInternal, "hash64_with_seeds", (ruby_method*) &cityhash_hash64_with_seeds, 3);
82
+
83
+ rb_define_singleton_method(mInternal, "hash128", (ruby_method*) &cityhash_hash128, 1);
84
+ rb_define_singleton_method(mInternal, "hash128_with_seed", (ruby_method*) &cityhash_hash128_with_seed, 2);
85
+
86
+ #ifdef __SSE4_2__
87
+ rb_define_singleton_method(mInternal, "hash128crc", (ruby_method*) &cityhash_hashcrc128, 1);
88
+ rb_define_singleton_method(mInternal, "hash128crc_with_seed", (ruby_method*) &cityhash_hashcrc128_with_seed, 2);
89
+
90
+ rb_define_singleton_method(mInternal, "hash256crc", (ruby_method*) &cityhash_hashcrc256, 1);
91
+ #endif
92
+ }
@@ -0,0 +1,11 @@
1
+ require 'mkmf'
2
+
3
+ cxx = ENV['CXX'] || with_config('CXX')
4
+ RbConfig::MAKEFILE_CONFIG['CXX'] = cxx if cxx
5
+
6
+ %w{g O3 Wall}.each do |flag|
7
+ flag = "-#{flag}"
8
+ $CPPFLAGS += " #{flag}" unless $CPPFLAGS.split.include? flag
9
+ end
10
+
11
+ create_makefile('cityhash/cityhash')
@@ -0,0 +1,66 @@
1
+ require 'cityhash/version'
2
+ require 'cityhash/cityhash'
3
+
4
+ module CityHash
5
+ LOW64_MASK = 0x0000000000000000ffffffffffffffff
6
+ HIGH64_MASK = 0xffffffffffffffff0000000000000000
7
+
8
+ def self.hash32(input)
9
+ input = input.to_s
10
+
11
+ Internal.hash32(input)
12
+ end
13
+
14
+ def self.hash64(input, seed1=nil, seed2=nil)
15
+ input = input.to_s
16
+
17
+ return Internal.hash64(input) if seed1.nil?
18
+ return Internal.hash64_with_seed(input, seed1.to_i) if seed2.nil?
19
+ Internal.hash64_with_seeds(input, seed1.to_i, seed2.to_i)
20
+ end
21
+
22
+ def self.hash128(input, seed=nil)
23
+ input = input.to_s
24
+
25
+ digest = if seed
26
+ Internal.hash128_with_seed(input, packed_seed(seed))
27
+ else
28
+ Internal.hash128(input)
29
+ end
30
+
31
+ unpacked_digest(digest)
32
+ end
33
+
34
+ if Internal.respond_to?(:hash128crc)
35
+ def self.hash128crc(input, seed=nil)
36
+ input = input.to_s
37
+
38
+ digest = if seed
39
+ Internal.hash128crc_with_seed(input, packed_seed(seed))
40
+ else
41
+ Internal.hash128crc(input)
42
+ end
43
+
44
+ unpacked_digest(digest)
45
+ end
46
+ end
47
+
48
+ if Internal.respond_to?(:hash256crc)
49
+ def self.hash256crc(input)
50
+ input = input.to_s
51
+ digest = Internal.hash256crc(input)
52
+
53
+ [0..7, 8..15, 16..23].map { |r| digest[r].unpack('Q').first.to_s }.join.to_i
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def self.packed_seed(seed)
60
+ [seed & LOW64_MASK, seed & HIGH64_MASK >> 64].pack('QQ')
61
+ end
62
+
63
+ def self.unpacked_digest(digest)
64
+ [0..7, 8..15].map { |r| digest[r].unpack('Q').first.to_s }.join.to_i
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module CityHash
2
+ VERSION = "0.9.1"
3
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ describe CityHash do
4
+ it 'returns 32bit hash' do
5
+ assert_equal 1633095781, CityHash.hash32("test")
6
+ end
7
+
8
+ it 'returns 64bit hash' do
9
+ assert_equal 8581389452482819506, CityHash.hash64("test")
10
+ end
11
+
12
+ it 'returns 64bit hash with a seed' do
13
+ assert_equal 9154302171269876511, CityHash.hash64("test", 12345)
14
+ end
15
+
16
+ it 'returns 64bit hash with seeds' do
17
+ assert_equal 4854399283587686019, CityHash.hash64("test", 12345, 54321)
18
+ end
19
+
20
+ it 'returns 128bit hash' do
21
+ assert_equal 124124989950401219618153994964897029896, CityHash.hash128("test")
22
+ end
23
+
24
+ it 'returns 128bit hash with seed' do
25
+ seed = (123 << 64) | 123
26
+ assert_equal 1834994000056895780313918994795281207519, CityHash.hash128("test", seed)
27
+ end
28
+
29
+ it 'returns 128bit crc hash' do
30
+ skip unless CityHash.respond_to?(:hash128crc)
31
+
32
+ assert_equal 124124989950401219618153994964897029896, CityHash.hash128crc("test")
33
+ end
34
+
35
+ it 'returns 128bit crc hash with seed' do
36
+ skip unless CityHash.respond_to?(:hash128crc)
37
+
38
+ seed = (123 << 64) | 123
39
+ assert_equal 1834994000056895780313918994795281207519, CityHash.hash128crc("test", seed)
40
+ end
41
+
42
+ it 'returns 256bit crc hash' do
43
+ skip unless CityHash.respond_to?(:hash256crc)
44
+
45
+ assert_equal 11964743055457135893972873789222488394617411264226841264756, CityHash.hash256crc("test")
46
+ end
47
+
48
+ it 'converts input data to string' do
49
+ assert_equal CityHash.hash128('1337'), CityHash.hash128(1337)
50
+ end
51
+
52
+ it 'does not core when you pass it nil' do
53
+ assert_raises TypeError do
54
+ CityHash::Internal.hash64(nil)
55
+ end
56
+
57
+ CityHash.hash64(nil)
58
+ end
59
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+
4
+ require 'cityhash'
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitshares-cityhash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - Vasiliy Ermolovich
8
+ - syalon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-10-25 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email:
16
+ - younash@gmail.com
17
+ - hanomirin@foxmail.com
18
+ executables: []
19
+ extensions:
20
+ - ext/cityhash/extconf.rb
21
+ extra_rdoc_files: []
22
+ files:
23
+ - ".gitignore"
24
+ - ".travis.yml"
25
+ - CHANGELOG.md
26
+ - Gemfile
27
+ - LICENSE.txt
28
+ - README.md
29
+ - Rakefile
30
+ - cityhash.gemspec
31
+ - ext/cityhash/city.cc
32
+ - ext/cityhash/city.h
33
+ - ext/cityhash/citycrc.h
34
+ - ext/cityhash/cityhash.cc
35
+ - ext/cityhash/extconf.rb
36
+ - lib/cityhash.rb
37
+ - lib/cityhash/version.rb
38
+ - test/cityhash_test.rb
39
+ - test/test_helper.rb
40
+ homepage: https://github.com/syalon/bitshares-cityhash.git
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project: cityhash
60
+ rubygems_version: 2.6.14.3
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: ruby bindings for google's cityhash
64
+ test_files: []