cityhash 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -7
- data/README.md +21 -16
- data/Rakefile +12 -46
- data/cityhash.gemspec +15 -69
- data/ext/cityhash/city.cc +229 -70
- data/ext/cityhash/city.h +1 -1
- data/ext/cityhash/cityhash.cc +47 -0
- data/ext/cityhash/extconf.rb +2 -6
- data/lib/cityhash.rb +12 -52
- data/lib/cityhash/version.rb +1 -10
- data/test/cityhash_test.rb +24 -0
- data/test/test_helper.rb +4 -0
- metadata +22 -90
- data/.document +0 -5
- data/Gemfile.lock +0 -23
- data/ext/cityhash/city_ruby_bridge.cpp +0 -19
- data/ext/cityhash/city_ruby_bridge.h +0 -8
- data/test/helper.rb +0 -18
- data/test/test_cityhash.rb +0 -26
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
### cityhash
|
1
|
+
### cityhash [![TravisCI](https://secure.travis-ci.org/nashby/cityhash.png?branch=master)](http://travis-ci.org/nashby/cityhash)
|
2
2
|
|
3
3
|
Ruby wrapper for google's cityhash.
|
4
4
|
|
5
5
|
### Install
|
6
|
-
|
6
|
+
|
7
7
|
gem install cityhash
|
8
8
|
|
9
9
|
### Usage
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
```ruby
|
12
|
+
require 'cityhash'
|
13
|
+
|
14
|
+
text = "test"
|
15
|
+
seed1 = 12345
|
16
|
+
seed2 = 54321
|
17
|
+
|
18
|
+
CityHash.hash64(text) # => 17703940110308125106
|
19
|
+
CityHash.hash64(text, seed1) # => 14900027982776226655
|
20
|
+
CityHash.hash64(text, seed1, seed2) # => 11136353178704814373
|
21
|
+
CityHash.hash128(text) # => 1800071687761605184910580728449884026697
|
22
|
+
CityHash.hash128(text, seed1) # => 6087407617808651818174120599816915369
|
23
|
+
```
|
24
|
+
|
23
25
|
### Contributing to cityhash
|
24
|
-
|
26
|
+
|
25
27
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
26
28
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
27
29
|
* Fork the project
|
@@ -34,10 +36,13 @@ Ruby wrapper for google's cityhash.
|
|
34
36
|
|
35
37
|
#### [Contributors](http://github.com/nashby/cityhash/contributors)
|
36
38
|
- [Johannes Holzfuß](http://github.com/DataWraith)
|
39
|
+
- [Quin Hoxie](https://github.com/qhoxie)
|
40
|
+
- [David Dai](https://github.com/newtonapple)
|
41
|
+
- [Sergey Nartimov](https://github.com/lest)
|
37
42
|
|
38
43
|
[Vasiliy Ermolovich](http://github.com/nashby/)<br/>
|
39
44
|
|
40
45
|
### Copyright
|
41
46
|
|
42
|
-
Copyright (c)
|
47
|
+
Copyright (c) 2012 Vasiliy Ermolovich. See LICENSE.txt for
|
43
48
|
further details.
|
data/Rakefile
CHANGED
@@ -1,54 +1,20 @@
|
|
1
|
-
require
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
$LOAD_PATH.unshift('lib')
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
require 'cityhash/version'
|
16
|
-
Jeweler::Tasks.new do |gem|
|
17
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
|
-
gem.name = "cityhash"
|
19
|
-
gem.homepage = "http://github.com/nashby/cityhash"
|
20
|
-
gem.license = "MIT"
|
21
|
-
gem.version = CityHash::Version::STRING
|
22
|
-
gem.summary = "ffi wrapper for google's cityhash"
|
23
|
-
gem.description = "ffi wrapper for google's cityhash"
|
24
|
-
gem.email = "younash@gmail.com"
|
25
|
-
gem.authors = ["nashby"]
|
26
|
-
gem.add_runtime_dependency 'ffi'
|
27
|
-
end
|
28
|
-
Jeweler::RubygemsDotOrgTasks.new
|
1
|
+
require "bundler/gem_tasks"
|
29
2
|
|
30
3
|
require 'rake/testtask'
|
31
|
-
|
32
|
-
test.libs << 'lib' << 'test'
|
33
|
-
test.pattern = 'test/**/test_*.rb'
|
34
|
-
test.verbose = true
|
35
|
-
end
|
4
|
+
require 'rake/clean'
|
36
5
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
test.verbose = true
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.pattern = 'test/*_test.rb'
|
9
|
+
t.verbose = true
|
42
10
|
end
|
43
11
|
|
12
|
+
desc "Run tests"
|
44
13
|
task :default => :test
|
45
14
|
|
46
|
-
require 'rake/
|
47
|
-
Rake::
|
48
|
-
|
49
|
-
|
50
|
-
rdoc.rdoc_dir = 'rdoc'
|
51
|
-
rdoc.title = "cityhash #{version}"
|
52
|
-
rdoc.rdoc_files.include('README*')
|
53
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
require 'rake/extensiontask'
|
16
|
+
Rake::ExtensionTask.new('cityhash') do |ext|
|
17
|
+
ext.lib_dir = 'lib/cityhash'
|
54
18
|
end
|
19
|
+
|
20
|
+
Rake::Task[:test].prerequisites << :compile
|
data/cityhash.gemspec
CHANGED
@@ -1,75 +1,21 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cityhash/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
6
|
+
s.name = "cityhash"
|
7
|
+
s.version = CityHash::VERSION
|
8
|
+
s.authors = ["Vasiliy Ermolovich"]
|
9
|
+
s.email = ["younash@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/nashby/cityhash"
|
11
|
+
s.summary = %q{ruby bindings for google's cityhash}
|
12
|
+
s.description = %q{ruby bindings for google's cityhash}
|
9
13
|
|
10
|
-
s.
|
11
|
-
s.authors = [%q{nashby}]
|
12
|
-
s.date = %q{2011-10-28}
|
13
|
-
s.description = %q{ffi wrapper for google's cityhash}
|
14
|
-
s.email = %q{younash@gmail.com}
|
15
|
-
s.extensions = [%q{ext/cityhash/extconf.rb}]
|
16
|
-
s.extra_rdoc_files = [
|
17
|
-
"LICENSE.txt",
|
18
|
-
"README.md"
|
19
|
-
]
|
20
|
-
s.files = [
|
21
|
-
".document",
|
22
|
-
"Gemfile",
|
23
|
-
"Gemfile.lock",
|
24
|
-
"LICENSE.txt",
|
25
|
-
"README.md",
|
26
|
-
"Rakefile",
|
27
|
-
"cityhash.gemspec",
|
28
|
-
"ext/cityhash/city.cc",
|
29
|
-
"ext/cityhash/city.h",
|
30
|
-
"ext/cityhash/city_ruby_bridge.cpp",
|
31
|
-
"ext/cityhash/city_ruby_bridge.h",
|
32
|
-
"ext/cityhash/extconf.rb",
|
33
|
-
"lib/cityhash.rb",
|
34
|
-
"lib/cityhash/version.rb",
|
35
|
-
"test/helper.rb",
|
36
|
-
"test/test_cityhash.rb"
|
37
|
-
]
|
38
|
-
s.homepage = %q{http://github.com/nashby/cityhash}
|
39
|
-
s.licenses = [%q{MIT}]
|
40
|
-
s.require_paths = [%q{lib}]
|
41
|
-
s.rubygems_version = %q{1.8.6}
|
42
|
-
s.summary = %q{ffi wrapper for google's cityhash}
|
43
|
-
s.test_files = [
|
44
|
-
"test/helper.rb",
|
45
|
-
"test/test_cityhash.rb"
|
46
|
-
]
|
14
|
+
s.rubyforge_project = "cityhash"
|
47
15
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
54
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
56
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
57
|
-
s.add_runtime_dependency(%q<ffi>, [">= 0"])
|
58
|
-
else
|
59
|
-
s.add_dependency(%q<ffi>, [">= 0"])
|
60
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
61
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
63
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
64
|
-
s.add_dependency(%q<ffi>, [">= 0"])
|
65
|
-
end
|
66
|
-
else
|
67
|
-
s.add_dependency(%q<ffi>, [">= 0"])
|
68
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
70
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
71
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
72
|
-
s.add_dependency(%q<ffi>, [">= 0"])
|
73
|
-
end
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.extensions = ["ext/cityhash/extconf.rb"]
|
74
21
|
end
|
75
|
-
|
data/ext/cityhash/city.cc
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
// THE SOFTWARE.
|
20
20
|
//
|
21
|
-
// CityHash
|
21
|
+
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
22
22
|
//
|
23
23
|
// This file provides CityHash64() and related functions.
|
24
24
|
//
|
@@ -30,20 +30,65 @@
|
|
30
30
|
#include "city.h"
|
31
31
|
|
32
32
|
#include <algorithm>
|
33
|
+
#include <string.h> // for memcpy and memset
|
33
34
|
|
34
35
|
using namespace std;
|
35
36
|
|
36
|
-
|
37
|
-
|
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
|
+
#if !defined(WORDS_BIGENDIAN)
|
50
|
+
|
51
|
+
#define uint32_in_expected_order(x) (x)
|
52
|
+
#define uint64_in_expected_order(x) (x)
|
53
|
+
|
54
|
+
#else
|
55
|
+
|
56
|
+
#ifdef _MSC_VER
|
57
|
+
#include <stdlib.h>
|
58
|
+
#define bswap_32(x) _byteswap_ulong(x)
|
59
|
+
#define bswap_64(x) _byteswap_uint64(x)
|
60
|
+
|
61
|
+
#elif defined(__APPLE__)
|
62
|
+
// Mac OS X / Darwin features
|
63
|
+
#include <libkern/OSByteOrder.h>
|
64
|
+
#define bswap_32(x) OSSwapInt32(x)
|
65
|
+
#define bswap_64(x) OSSwapInt64(x)
|
66
|
+
|
67
|
+
#else
|
68
|
+
#include <byteswap.h>
|
69
|
+
#endif
|
70
|
+
|
71
|
+
#define uint32_in_expected_order(x) (bswap_32(x))
|
72
|
+
#define uint64_in_expected_order(x) (bswap_64(x))
|
73
|
+
|
74
|
+
#endif // WORDS_BIGENDIAN
|
38
75
|
|
39
76
|
#if !defined(LIKELY)
|
40
|
-
#if
|
77
|
+
#if HAVE_BUILTIN_EXPECT
|
41
78
|
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
42
79
|
#else
|
43
80
|
#define LIKELY(x) (x)
|
44
81
|
#endif
|
45
82
|
#endif
|
46
83
|
|
84
|
+
static uint64 Fetch64(const char *p) {
|
85
|
+
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
|
86
|
+
}
|
87
|
+
|
88
|
+
static uint32 Fetch32(const char *p) {
|
89
|
+
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
|
90
|
+
}
|
91
|
+
|
47
92
|
// Some primes between 2^63 and 2^64 for various uses.
|
48
93
|
static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
|
49
94
|
static const uint64 k1 = 0xb492b66fbe98f273ULL;
|
@@ -74,13 +119,13 @@ static uint64 HashLen16(uint64 u, uint64 v) {
|
|
74
119
|
|
75
120
|
static uint64 HashLen0to16(const char *s, size_t len) {
|
76
121
|
if (len > 8) {
|
77
|
-
uint64 a =
|
78
|
-
uint64 b =
|
122
|
+
uint64 a = Fetch64(s);
|
123
|
+
uint64 b = Fetch64(s + len - 8);
|
79
124
|
return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b;
|
80
125
|
}
|
81
126
|
if (len >= 4) {
|
82
|
-
uint64 a =
|
83
|
-
return HashLen16(len + (a << 3),
|
127
|
+
uint64 a = Fetch32(s);
|
128
|
+
return HashLen16(len + (a << 3), Fetch32(s + len - 4));
|
84
129
|
}
|
85
130
|
if (len > 0) {
|
86
131
|
uint8 a = s[0];
|
@@ -96,10 +141,10 @@ static uint64 HashLen0to16(const char *s, size_t len) {
|
|
96
141
|
// This probably works well for 16-byte strings as well, but it may be overkill
|
97
142
|
// in that case.
|
98
143
|
static uint64 HashLen17to32(const char *s, size_t len) {
|
99
|
-
uint64 a =
|
100
|
-
uint64 b =
|
101
|
-
uint64 c =
|
102
|
-
uint64 d =
|
144
|
+
uint64 a = Fetch64(s) * k1;
|
145
|
+
uint64 b = Fetch64(s + 8);
|
146
|
+
uint64 c = Fetch64(s + len - 8) * k2;
|
147
|
+
uint64 d = Fetch64(s + len - 16) * k0;
|
103
148
|
return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d,
|
104
149
|
a + Rotate(b ^ k3, 20) - c + len);
|
105
150
|
}
|
@@ -120,32 +165,32 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds(
|
|
120
165
|
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
121
166
|
static pair<uint64, uint64> WeakHashLen32WithSeeds(
|
122
167
|
const char* s, uint64 a, uint64 b) {
|
123
|
-
return WeakHashLen32WithSeeds(
|
124
|
-
|
125
|
-
|
126
|
-
|
168
|
+
return WeakHashLen32WithSeeds(Fetch64(s),
|
169
|
+
Fetch64(s + 8),
|
170
|
+
Fetch64(s + 16),
|
171
|
+
Fetch64(s + 24),
|
127
172
|
a,
|
128
173
|
b);
|
129
174
|
}
|
130
175
|
|
131
176
|
// Return an 8-byte hash for 33 to 64 bytes.
|
132
177
|
static uint64 HashLen33to64(const char *s, size_t len) {
|
133
|
-
uint64 z =
|
134
|
-
uint64 a =
|
178
|
+
uint64 z = Fetch64(s + 24);
|
179
|
+
uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0;
|
135
180
|
uint64 b = Rotate(a + z, 52);
|
136
181
|
uint64 c = Rotate(a, 37);
|
137
|
-
a +=
|
182
|
+
a += Fetch64(s + 8);
|
138
183
|
c += Rotate(a, 7);
|
139
|
-
a +=
|
184
|
+
a += Fetch64(s + 16);
|
140
185
|
uint64 vf = a + z;
|
141
186
|
uint64 vs = b + Rotate(a, 31) + c;
|
142
|
-
a =
|
143
|
-
z =
|
187
|
+
a = Fetch64(s + 16) + Fetch64(s + len - 32);
|
188
|
+
z = Fetch64(s + len - 8);
|
144
189
|
b = Rotate(a + z, 52);
|
145
190
|
c = Rotate(a, 37);
|
146
|
-
a +=
|
191
|
+
a += Fetch64(s + len - 24);
|
147
192
|
c += Rotate(a, 7);
|
148
|
-
a +=
|
193
|
+
a += Fetch64(s + len - 16);
|
149
194
|
uint64 wf = a + z;
|
150
195
|
uint64 ws = b + Rotate(a, 31) + c;
|
151
196
|
uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
|
@@ -165,25 +210,23 @@ uint64 CityHash64(const char *s, size_t len) {
|
|
165
210
|
|
166
211
|
// For strings over 64 bytes we hash the end first, and then as we
|
167
212
|
// loop we keep 56 bytes of state: v, w, x, y, and z.
|
168
|
-
uint64 x =
|
169
|
-
uint64 y =
|
170
|
-
uint64 z =
|
171
|
-
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len,
|
172
|
-
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32,
|
173
|
-
|
174
|
-
x = Rotate(z + x, 39) * k1;
|
175
|
-
y = Rotate(y, 33) * k1;
|
213
|
+
uint64 x = Fetch64(s + len - 40);
|
214
|
+
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
215
|
+
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
216
|
+
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
217
|
+
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
218
|
+
x = x * k1 + Fetch64(s);
|
176
219
|
|
177
220
|
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
178
221
|
len = (len - 1) & ~static_cast<size_t>(63);
|
179
222
|
do {
|
180
|
-
x = Rotate(x + y + v.first +
|
181
|
-
y = Rotate(y + v.second +
|
223
|
+
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
224
|
+
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
182
225
|
x ^= w.second;
|
183
|
-
y
|
184
|
-
z = Rotate(z
|
226
|
+
y += v.first + Fetch64(s + 40);
|
227
|
+
z = Rotate(z + w.first, 33) * k1;
|
185
228
|
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
186
|
-
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
|
229
|
+
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
187
230
|
std::swap(z, x);
|
188
231
|
s += 64;
|
189
232
|
len -= 64;
|
@@ -202,25 +245,26 @@ uint64 CityHash64WithSeeds(const char *s, size_t len,
|
|
202
245
|
}
|
203
246
|
|
204
247
|
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
205
|
-
// of any length representable in
|
248
|
+
// of any length representable in signed long. Based on City and Murmur.
|
206
249
|
static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
|
207
250
|
uint64 a = Uint128Low64(seed);
|
208
251
|
uint64 b = Uint128High64(seed);
|
209
252
|
uint64 c = 0;
|
210
253
|
uint64 d = 0;
|
211
|
-
|
254
|
+
signed long l = len - 16;
|
212
255
|
if (l <= 0) { // len <= 16
|
256
|
+
a = ShiftMix(a * k1) * k1;
|
213
257
|
c = b * k1 + HashLen0to16(s, len);
|
214
|
-
d =
|
258
|
+
d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
|
215
259
|
} else { // len > 16
|
216
|
-
c = HashLen16(
|
217
|
-
d = HashLen16(b + len, c +
|
260
|
+
c = HashLen16(Fetch64(s + len - 8) + k1, a);
|
261
|
+
d = HashLen16(b + len, c + Fetch64(s + len - 16));
|
218
262
|
a += d;
|
219
263
|
do {
|
220
|
-
a ^= ShiftMix(
|
264
|
+
a ^= ShiftMix(Fetch64(s) * k1) * k1;
|
221
265
|
a *= k1;
|
222
266
|
b ^= a;
|
223
|
-
c ^= ShiftMix(
|
267
|
+
c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
|
224
268
|
c *= k1;
|
225
269
|
d ^= c;
|
226
270
|
s += 16;
|
@@ -243,49 +287,50 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
|
|
243
287
|
uint64 x = Uint128Low64(seed);
|
244
288
|
uint64 y = Uint128High64(seed);
|
245
289
|
uint64 z = len * k1;
|
246
|
-
v.first = Rotate(y ^ k1, 49) * k1 +
|
247
|
-
v.second = Rotate(v.first, 42) * k1 +
|
290
|
+
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
|
291
|
+
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
|
248
292
|
w.first = Rotate(y + z, 35) * k1 + x;
|
249
|
-
w.second = Rotate(x +
|
293
|
+
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
|
250
294
|
|
251
295
|
// This is the same inner loop as CityHash64(), manually unrolled.
|
252
296
|
do {
|
253
|
-
x = Rotate(x + y + v.first +
|
254
|
-
y = Rotate(y + v.second +
|
297
|
+
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
298
|
+
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
255
299
|
x ^= w.second;
|
256
|
-
y
|
257
|
-
z = Rotate(z
|
300
|
+
y += v.first + Fetch64(s + 40);
|
301
|
+
z = Rotate(z + w.first, 33) * k1;
|
258
302
|
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
259
|
-
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
|
303
|
+
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
260
304
|
std::swap(z, x);
|
261
305
|
s += 64;
|
262
|
-
x = Rotate(x + y + v.first +
|
263
|
-
y = Rotate(y + v.second +
|
306
|
+
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
307
|
+
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
264
308
|
x ^= w.second;
|
265
|
-
y
|
266
|
-
z = Rotate(z
|
309
|
+
y += v.first + Fetch64(s + 40);
|
310
|
+
z = Rotate(z + w.first, 33) * k1;
|
267
311
|
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
268
|
-
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
|
312
|
+
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
269
313
|
std::swap(z, x);
|
270
314
|
s += 64;
|
271
315
|
len -= 128;
|
272
316
|
} while (LIKELY(len >= 128));
|
273
|
-
y += Rotate(w.first, 37) * k0 + z;
|
274
317
|
x += Rotate(v.first + z, 49) * k0;
|
318
|
+
z += Rotate(w.first, 37) * k0;
|
275
319
|
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
276
320
|
for (size_t tail_done = 0; tail_done < len; ) {
|
277
321
|
tail_done += 32;
|
278
|
-
y = Rotate(
|
279
|
-
w.first +=
|
280
|
-
x =
|
281
|
-
w.
|
282
|
-
|
322
|
+
y = Rotate(x + y, 42) * k0 + v.second;
|
323
|
+
w.first += Fetch64(s + len - tail_done + 16);
|
324
|
+
x = x * k0 + w.first;
|
325
|
+
z += w.second + Fetch64(s + len - tail_done);
|
326
|
+
w.second += v.first;
|
327
|
+
v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
|
283
328
|
}
|
284
|
-
// At this point our
|
329
|
+
// At this point our 56 bytes of state should contain more than
|
285
330
|
// enough information for a strong 128-bit hash. We use two
|
286
|
-
// different
|
331
|
+
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
287
332
|
x = HashLen16(x, v.first);
|
288
|
-
y = HashLen16(y, w.first);
|
333
|
+
y = HashLen16(y + z, w.first);
|
289
334
|
return uint128(HashLen16(x + v.second, w.second) + y,
|
290
335
|
HashLen16(x + w.second, y + v.second));
|
291
336
|
}
|
@@ -294,14 +339,128 @@ uint128 CityHash128(const char *s, size_t len) {
|
|
294
339
|
if (len >= 16) {
|
295
340
|
return CityHash128WithSeed(s + 16,
|
296
341
|
len - 16,
|
297
|
-
uint128(
|
298
|
-
|
342
|
+
uint128(Fetch64(s) ^ k3,
|
343
|
+
Fetch64(s + 8)));
|
299
344
|
} else if (len >= 8) {
|
300
345
|
return CityHash128WithSeed(NULL,
|
301
346
|
0,
|
302
|
-
uint128(
|
303
|
-
|
347
|
+
uint128(Fetch64(s) ^ (len * k0),
|
348
|
+
Fetch64(s + len - 8) ^ k1));
|
304
349
|
} else {
|
305
350
|
return CityHash128WithSeed(s, len, uint128(k0, k1));
|
306
351
|
}
|
307
352
|
}
|
353
|
+
|
354
|
+
#ifdef __SSE4_2__
|
355
|
+
#include <citycrc.h>
|
356
|
+
#include <nmmintrin.h>
|
357
|
+
|
358
|
+
// Requires len >= 240.
|
359
|
+
static void CityHashCrc256Long(const char *s, size_t len,
|
360
|
+
uint32 seed, uint64 *result) {
|
361
|
+
uint64 a = Fetch64(s + 56) + k0;
|
362
|
+
uint64 b = Fetch64(s + 96) + k0;
|
363
|
+
uint64 c = result[0] = HashLen16(b, len);
|
364
|
+
uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
|
365
|
+
uint64 e = Fetch64(s + 184) + seed;
|
366
|
+
uint64 f = seed;
|
367
|
+
uint64 g = 0;
|
368
|
+
uint64 h = 0;
|
369
|
+
uint64 i = 0;
|
370
|
+
uint64 j = 0;
|
371
|
+
uint64 t = c + d;
|
372
|
+
|
373
|
+
// 240 bytes of input per iter.
|
374
|
+
size_t iters = len / 240;
|
375
|
+
len -= iters * 240;
|
376
|
+
do {
|
377
|
+
#define CHUNK(multiplier, z) \
|
378
|
+
{ \
|
379
|
+
uint64 old_a = a; \
|
380
|
+
a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \
|
381
|
+
b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \
|
382
|
+
c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \
|
383
|
+
d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \
|
384
|
+
e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \
|
385
|
+
t = old_a; \
|
386
|
+
} \
|
387
|
+
f = _mm_crc32_u64(f, a); \
|
388
|
+
g = _mm_crc32_u64(g, b); \
|
389
|
+
h = _mm_crc32_u64(h, c); \
|
390
|
+
i = _mm_crc32_u64(i, d); \
|
391
|
+
j = _mm_crc32_u64(j, e); \
|
392
|
+
s += 40
|
393
|
+
|
394
|
+
CHUNK(1, 1); CHUNK(k0, 0);
|
395
|
+
CHUNK(1, 1); CHUNK(k0, 0);
|
396
|
+
CHUNK(1, 1); CHUNK(k0, 0);
|
397
|
+
} while (--iters > 0);
|
398
|
+
|
399
|
+
while (len >= 40) {
|
400
|
+
CHUNK(k0, 0);
|
401
|
+
len -= 40;
|
402
|
+
}
|
403
|
+
if (len > 0) {
|
404
|
+
s = s + len - 40;
|
405
|
+
CHUNK(k0, 0);
|
406
|
+
}
|
407
|
+
j += i << 32;
|
408
|
+
a = HashLen16(a, j);
|
409
|
+
h += g << 32;
|
410
|
+
b += h;
|
411
|
+
c = HashLen16(c, f) + i;
|
412
|
+
d = HashLen16(d, e + result[0]);
|
413
|
+
j += e;
|
414
|
+
i += HashLen16(h, t);
|
415
|
+
e = HashLen16(a, d) + j;
|
416
|
+
f = HashLen16(b, c) + a;
|
417
|
+
g = HashLen16(j, i) + c;
|
418
|
+
result[0] = e + f + g + h;
|
419
|
+
a = ShiftMix((a + g) * k0) * k0 + b;
|
420
|
+
result[1] += a + result[0];
|
421
|
+
a = ShiftMix(a * k0) * k0 + c;
|
422
|
+
result[2] = a + result[1];
|
423
|
+
a = ShiftMix((a + e) * k0) * k0;
|
424
|
+
result[3] = a + result[2];
|
425
|
+
}
|
426
|
+
|
427
|
+
// Requires len < 240.
|
428
|
+
static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) {
|
429
|
+
char buf[240];
|
430
|
+
memcpy(buf, s, len);
|
431
|
+
memset(buf + len, 0, 240 - len);
|
432
|
+
CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
|
433
|
+
}
|
434
|
+
|
435
|
+
void CityHashCrc256(const char *s, size_t len, uint64 *result) {
|
436
|
+
if (LIKELY(len >= 240)) {
|
437
|
+
CityHashCrc256Long(s, len, 0, result);
|
438
|
+
} else {
|
439
|
+
CityHashCrc256Short(s, len, result);
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
444
|
+
if (len <= 900) {
|
445
|
+
return CityHash128WithSeed(s, len, seed);
|
446
|
+
} else {
|
447
|
+
uint64 result[4];
|
448
|
+
CityHashCrc256(s, len, result);
|
449
|
+
uint64 u = Uint128High64(seed) + result[0];
|
450
|
+
uint64 v = Uint128Low64(seed) + result[1];
|
451
|
+
return uint128(HashLen16(u, v + result[2]),
|
452
|
+
HashLen16(Rotate(v, 32), u * k0 + result[3]));
|
453
|
+
}
|
454
|
+
}
|
455
|
+
|
456
|
+
uint128 CityHashCrc128(const char *s, size_t len) {
|
457
|
+
if (len <= 900) {
|
458
|
+
return CityHash128(s, len);
|
459
|
+
} else {
|
460
|
+
uint64 result[4];
|
461
|
+
CityHashCrc256(s, len, result);
|
462
|
+
return uint128(result[2], result[3]);
|
463
|
+
}
|
464
|
+
}
|
465
|
+
|
466
|
+
#endif
|
data/ext/cityhash/city.h
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
// THE SOFTWARE.
|
20
20
|
//
|
21
|
-
// CityHash
|
21
|
+
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
22
22
|
//
|
23
23
|
// This file provides a few functions for hashing strings. On x86-64
|
24
24
|
// hardware in 2011, CityHash64() is faster than other high-quality
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "city.h"
|
3
|
+
|
4
|
+
// Use this typedef to make the compiler happy when
|
5
|
+
// calling rb_define_method()
|
6
|
+
typedef VALUE (ruby_method)(...);
|
7
|
+
|
8
|
+
extern "C" VALUE cityhash_hash64(VALUE mod, VALUE input)
|
9
|
+
{
|
10
|
+
return ULL2NUM(CityHash64(StringValuePtr(input), RSTRING_LEN(input)));
|
11
|
+
}
|
12
|
+
|
13
|
+
extern "C" VALUE cityhash_hash64_with_seed(VALUE mod, VALUE input, VALUE seed)
|
14
|
+
{
|
15
|
+
return ULL2NUM(CityHash64WithSeed(StringValuePtr(input), RSTRING_LEN(input), NUM2ULL(seed)));
|
16
|
+
}
|
17
|
+
|
18
|
+
extern "C" VALUE cityhash_hash64_with_seeds(VALUE mod, VALUE input, VALUE seed1, VALUE seed2)
|
19
|
+
{
|
20
|
+
return ULL2NUM(CityHash64WithSeeds(StringValuePtr(input), RSTRING_LEN(input), NUM2ULL(seed1), NUM2ULL(seed2)));
|
21
|
+
}
|
22
|
+
|
23
|
+
extern "C" VALUE cityhash_hash128(VALUE mod, VALUE input)
|
24
|
+
{
|
25
|
+
uint128 hash = CityHash128(StringValuePtr(input), RSTRING_LEN(input));
|
26
|
+
return rb_str_new((char *)&hash, sizeof(hash));
|
27
|
+
}
|
28
|
+
|
29
|
+
extern "C" VALUE cityhash_hash128_with_seed(VALUE mod, VALUE input, VALUE seed_string)
|
30
|
+
{
|
31
|
+
uint128 seed = *(uint128 *)StringValuePtr(seed_string);
|
32
|
+
uint128 hash = CityHash128WithSeed(StringValuePtr(input), RSTRING_LEN(input), seed);
|
33
|
+
return rb_str_new((char *)&hash, sizeof(hash));
|
34
|
+
}
|
35
|
+
|
36
|
+
extern "C" void Init_cityhash()
|
37
|
+
{
|
38
|
+
VALUE mCityHash = rb_define_module("CityHash");
|
39
|
+
VALUE mInternal = rb_define_module_under(mCityHash, "Internal");
|
40
|
+
|
41
|
+
rb_define_singleton_method(mInternal, "hash64", (ruby_method*) &cityhash_hash64, 1);
|
42
|
+
rb_define_singleton_method(mInternal, "hash64_with_seed", (ruby_method*) &cityhash_hash64_with_seed, 2);
|
43
|
+
rb_define_singleton_method(mInternal, "hash64_with_seeds", (ruby_method*) &cityhash_hash64_with_seeds, 3);
|
44
|
+
|
45
|
+
rb_define_singleton_method(mInternal, "hash128", (ruby_method*) &cityhash_hash128, 1);
|
46
|
+
rb_define_singleton_method(mInternal, "hash128_with_seed", (ruby_method*) &cityhash_hash128_with_seed, 2);
|
47
|
+
}
|
data/ext/cityhash/extconf.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
%w{g O3 Wall rdynamic}.each do |flag|
|
3
|
+
%w{g O3 Wall}.each do |flag|
|
6
4
|
flag = "-#{flag}"
|
7
5
|
$CPPFLAGS += " #{flag}" unless $CPPFLAGS.split.include? flag
|
8
6
|
end
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
create_makefile('cityhash')
|
8
|
+
create_makefile('cityhash/cityhash')
|
data/lib/cityhash.rb
CHANGED
@@ -1,63 +1,23 @@
|
|
1
|
-
require '
|
1
|
+
require 'cityhash/version'
|
2
|
+
require 'cityhash/cityhash'
|
2
3
|
|
3
4
|
module CityHash
|
4
|
-
|
5
5
|
LOW64_MASK = 0x0000000000000000ffffffffffffffff
|
6
6
|
HIGH64_MASK = 0xffffffffffffffff0000000000000000
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
case RUBY_PLATFORM
|
13
|
-
when /darwin/
|
14
|
-
File.join(File.dirname(__FILE__), '..', 'ext', 'cityhash', 'cityhash.bundle')
|
15
|
-
when /mingw|mswin|linux/
|
16
|
-
File.join(File.dirname(__FILE__), '..', 'ext', 'cityhash', 'cityhash.so')
|
17
|
-
else
|
18
|
-
File.join(File.dirname(__FILE__), '..', 'ext', 'cityhash', "cityhash.#{RbConfig::CONFIG['DLEXT']}")
|
19
|
-
end
|
20
|
-
)
|
21
|
-
|
22
|
-
attach_function :city_hash64, :CityHash64, [:string, :size_t], :uint64
|
23
|
-
attach_function :city_hash64_with_seed, :CityHash64WithSeed, [:string, :size_t, :uint64], :uint64
|
24
|
-
attach_function :city_hash64_with_seeds, :CityHash64WithSeeds, [:string, :size_t, :uint64, :uint64], :uint64
|
25
|
-
attach_function :city_hash128, :CityHash128String, [:string, :size_t], :string
|
26
|
-
attach_function :city_hash128_with_seed, :CityHash128WithSeedString, [:string, :size_t, :uint64, :uint64], :string
|
8
|
+
def self.hash64(input, seed1=nil, seed2=nil)
|
9
|
+
return Internal.hash64(input) if seed1.nil?
|
10
|
+
return Internal.hash64_with_seed(input, seed1.to_i) if seed2.nil?
|
11
|
+
Internal.hash64_with_seeds(input, seed1.to_i, seed2.to_i)
|
27
12
|
end
|
28
13
|
|
29
|
-
def self.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
if input_str.respond_to?(:bytesize)
|
34
|
-
len = input_str.bytesize
|
14
|
+
def self.hash128(input, seed=nil)
|
15
|
+
if seed
|
16
|
+
seed = [seed & LOW64_MASK, seed & HIGH64_MASK >> 64].pack('QQ')
|
17
|
+
digest = Internal.hash128_with_seed(input, seed)
|
35
18
|
else
|
36
|
-
|
19
|
+
digest = Internal.hash128(input)
|
37
20
|
end
|
38
|
-
|
39
|
-
return CityHash::Internal.city_hash64(input_str, len) if seed1.nil?
|
40
|
-
return CityHash::Internal.city_hash64_with_seed(input_str, len, seed1.to_i & LOW64_MASK) if seed2.nil?
|
41
|
-
|
42
|
-
CityHash::Internal.city_hash64_with_seeds(input_str, len, seed1.to_i & LOW64_MASK, seed2.to_i & LOW64_MASK)
|
21
|
+
[0..7, 8..15].map { |r| digest[r].unpack('Q').first.to_s }.join.to_i
|
43
22
|
end
|
44
|
-
|
45
|
-
def self.hash128(input, seed = nil)
|
46
|
-
input_str = input.to_s
|
47
|
-
|
48
|
-
# Ruby 1.8 compatibility
|
49
|
-
if input_str.respond_to?(:bytesize)
|
50
|
-
len = input_str.bytesize
|
51
|
-
else
|
52
|
-
len = input_str.size
|
53
|
-
end
|
54
|
-
|
55
|
-
return CityHash::Internal.city_hash128(input_str, len).to_i if seed.nil?
|
56
|
-
|
57
|
-
seed_low = seed.to_i & LOW64_MASK
|
58
|
-
seed_high = (seed.to_i & HIGH64_MASK) >> 64
|
59
|
-
|
60
|
-
CityHash::Internal.city_hash128_with_seed(input_str, len, seed_low, seed_high).to_i
|
61
|
-
end
|
62
|
-
|
63
23
|
end
|
data/lib/cityhash/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe CityHash do
|
4
|
+
it 'returns 64bit hash' do
|
5
|
+
assert_equal 17703940110308125106, CityHash.hash64("test")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns 64bit hash with a seed" do
|
9
|
+
assert_equal 14900027982776226655, CityHash.hash64("test", 12345)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns 64bit hash with seeds" do
|
13
|
+
assert_equal 11136353178704814373, CityHash.hash64("test", 12345, 54321)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns 128bit hash" do
|
17
|
+
assert_equal 1800071687761605184910580728449884026697, CityHash.hash128("test")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns 128bit hash with seed" do
|
21
|
+
seed = (123 << 64) | 123
|
22
|
+
assert_equal 1631427474705635869517741677842296176559, CityHash.hash128("test", seed)
|
23
|
+
end
|
24
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,110 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cityhash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
-
|
8
|
+
- Vasiliy Ermolovich
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: *24780520
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: shoulda
|
27
|
-
requirement: &24779860 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - ! '>='
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
33
|
-
type: :development
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *24779860
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: bundler
|
38
|
-
requirement: &24779220 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 1.0.0
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *24779220
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: jeweler
|
49
|
-
requirement: &24778500 !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.5.2
|
55
|
-
type: :development
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: *24778500
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: rcov
|
60
|
-
requirement: &24777780 !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
|
-
requirements:
|
63
|
-
- - ! '>='
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: '0'
|
66
|
-
type: :development
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: *24777780
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: ffi
|
71
|
-
requirement: &24776560 !ruby/object:Gem::Requirement
|
72
|
-
none: false
|
73
|
-
requirements:
|
74
|
-
- - ! '>='
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '0'
|
77
|
-
type: :runtime
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: *24776560
|
80
|
-
description: ffi wrapper for google's cityhash
|
81
|
-
email: younash@gmail.com
|
12
|
+
date: 2012-04-07 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: ruby bindings for google's cityhash
|
15
|
+
email:
|
16
|
+
- younash@gmail.com
|
82
17
|
executables: []
|
83
18
|
extensions:
|
84
19
|
- ext/cityhash/extconf.rb
|
85
|
-
extra_rdoc_files:
|
86
|
-
- LICENSE.txt
|
87
|
-
- README.md
|
20
|
+
extra_rdoc_files: []
|
88
21
|
files:
|
89
|
-
- .
|
22
|
+
- .gitignore
|
23
|
+
- .travis.yml
|
90
24
|
- Gemfile
|
91
|
-
- Gemfile.lock
|
92
25
|
- LICENSE.txt
|
93
26
|
- README.md
|
94
27
|
- Rakefile
|
95
28
|
- cityhash.gemspec
|
96
29
|
- ext/cityhash/city.cc
|
97
30
|
- ext/cityhash/city.h
|
98
|
-
- ext/cityhash/
|
99
|
-
- ext/cityhash/city_ruby_bridge.h
|
31
|
+
- ext/cityhash/cityhash.cc
|
100
32
|
- ext/cityhash/extconf.rb
|
101
33
|
- lib/cityhash.rb
|
102
34
|
- lib/cityhash/version.rb
|
103
|
-
- test/
|
104
|
-
- test/
|
35
|
+
- test/cityhash_test.rb
|
36
|
+
- test/test_helper.rb
|
105
37
|
homepage: http://github.com/nashby/cityhash
|
106
|
-
licenses:
|
107
|
-
- MIT
|
38
|
+
licenses: []
|
108
39
|
post_install_message:
|
109
40
|
rdoc_options: []
|
110
41
|
require_paths:
|
@@ -117,19 +48,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
48
|
version: '0'
|
118
49
|
segments:
|
119
50
|
- 0
|
120
|
-
hash:
|
51
|
+
hash: 268501841747995875
|
121
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
53
|
none: false
|
123
54
|
requirements:
|
124
55
|
- - ! '>='
|
125
56
|
- !ruby/object:Gem::Version
|
126
57
|
version: '0'
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
hash: 268501841747995875
|
127
61
|
requirements: []
|
128
|
-
rubyforge_project:
|
129
|
-
rubygems_version: 1.8.
|
62
|
+
rubyforge_project: cityhash
|
63
|
+
rubygems_version: 1.8.19
|
130
64
|
signing_key:
|
131
65
|
specification_version: 3
|
132
|
-
summary:
|
133
|
-
test_files:
|
134
|
-
- test/helper.rb
|
135
|
-
- test/test_cityhash.rb
|
66
|
+
summary: ruby bindings for google's cityhash
|
67
|
+
test_files: []
|
data/.document
DELETED
data/Gemfile.lock
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
ffi (1.0.7)
|
5
|
-
rake (>= 0.8.7)
|
6
|
-
git (1.2.5)
|
7
|
-
jeweler (1.5.2)
|
8
|
-
bundler (~> 1.0.0)
|
9
|
-
git (>= 1.2.5)
|
10
|
-
rake
|
11
|
-
rake (0.8.7)
|
12
|
-
rcov (0.9.9)
|
13
|
-
shoulda (2.11.3)
|
14
|
-
|
15
|
-
PLATFORMS
|
16
|
-
ruby
|
17
|
-
|
18
|
-
DEPENDENCIES
|
19
|
-
bundler (~> 1.0.0)
|
20
|
-
ffi
|
21
|
-
jeweler (~> 1.5.2)
|
22
|
-
rcov
|
23
|
-
shoulda
|
@@ -1,19 +0,0 @@
|
|
1
|
-
#include "city_ruby_bridge.h"
|
2
|
-
#include <sstream>
|
3
|
-
|
4
|
-
const char* CityHash128String(const char *s, size_t len)
|
5
|
-
{
|
6
|
-
std::ostringstream str;
|
7
|
-
str << Uint128Low64(CityHash128(s, len)) << Uint128High64(CityHash128(s, len));
|
8
|
-
|
9
|
-
return str.str().c_str();
|
10
|
-
}
|
11
|
-
|
12
|
-
const char* CityHash128WithSeedString(const char *s, size_t len, uint64 seed1, uint64 seed2)
|
13
|
-
{
|
14
|
-
uint128 seed(seed1, seed2);
|
15
|
-
std::ostringstream str;
|
16
|
-
str << Uint128Low64(CityHash128WithSeed(s, len, seed)) << Uint128High64(CityHash128WithSeed(s, len, seed));
|
17
|
-
|
18
|
-
return str.str().c_str();
|
19
|
-
}
|
@@ -1,8 +0,0 @@
|
|
1
|
-
#include "city.h"
|
2
|
-
|
3
|
-
typedef uint64_t uint64;
|
4
|
-
typedef std::pair<uint64, uint64> uint128;
|
5
|
-
|
6
|
-
extern "C" const char* CityHash128String(const char *s, size_t len);
|
7
|
-
|
8
|
-
extern "C" const char* CityHash128WithSeedString(const char *s, size_t len, uint64 seed1, uint64 seed2);
|
data/test/helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'test/unit'
|
11
|
-
require 'shoulda'
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
-
require 'cityhash'
|
16
|
-
|
17
|
-
class Test::Unit::TestCase
|
18
|
-
end
|
data/test/test_cityhash.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestCityhash < Test::Unit::TestCase
|
4
|
-
|
5
|
-
should "return 64bit hash" do
|
6
|
-
assert_equal 17703940110308125106, CityHash.hash64("test")
|
7
|
-
end
|
8
|
-
|
9
|
-
should "return 64bit hash with a seed" do
|
10
|
-
assert_equal 14900027982776226655, CityHash.hash64("test", 12345)
|
11
|
-
end
|
12
|
-
|
13
|
-
should "return 64bit hash with seeds" do
|
14
|
-
assert_equal 11136353178704814373, CityHash.hash64("test", 12345, 54321)
|
15
|
-
end
|
16
|
-
|
17
|
-
should "return 128bit hash" do
|
18
|
-
assert_equal 130554790001792308794529643941127319555, CityHash.hash128("test")
|
19
|
-
end
|
20
|
-
|
21
|
-
should "return 128bit hash with seed" do
|
22
|
-
seed = (123 << 64) | 123
|
23
|
-
assert_equal 183946415266487905135364192266033899899, CityHash.hash128("test", seed)
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|