cityhash 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ *.so
2
+ *.bundle
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+ tmp/*
7
+ vendor/bundle
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile CHANGED
@@ -1,10 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "ffi"
3
+ gemspec
4
4
 
5
- group :development do
6
- gem "shoulda", ">= 0"
7
- gem "bundler", "~> 1.0.0"
8
- gem "jeweler", "~> 1.5.2"
9
- gem "rcov", ">= 0"
10
- end
5
+ gem 'rake'
6
+ gem 'rake-compiler'
7
+ gem 'minitest', '~> 2.11.0'
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
- require 'cityhash'
12
-
13
- text = "test"
14
- seed1 = 12345
15
- seed2 = 54321
16
-
17
- CityHash.hash64(text) # => 17703940110308125106
18
- CityHash.hash64(text, seed1) # => 14900027982776226655
19
- CityHash.hash64(text, seed1, seed2) # => 11136353178704814373
20
- CityHash.hash128(text) # => 130554790001792308794529643941127319555
21
- CityHash.hash128(text, seed1) # => 1238187875708097619810923284135194760226
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) 2011 nashby. See LICENSE.txt for
47
+ Copyright (c) 2012 Vasiliy Ermolovich. See LICENSE.txt for
43
48
  further details.
data/Rakefile CHANGED
@@ -1,54 +1,20 @@
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 '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
- Rake::TestTask.new(:test) do |test|
32
- test.libs << 'lib' << 'test'
33
- test.pattern = 'test/**/test_*.rb'
34
- test.verbose = true
35
- end
4
+ require 'rake/clean'
36
5
 
37
- require 'rcov/rcovtask'
38
- Rcov::RcovTask.new do |test|
39
- test.libs << 'test'
40
- test.pattern = 'test/**/test_*.rb'
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/rdoctask'
47
- Rake::RDocTask.new do |rdoc|
48
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
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
@@ -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 = %q{cityhash}
8
- s.version = "0.5.0"
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.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
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
- if s.respond_to? :specification_version then
49
- s.specification_version = 3
50
-
51
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
- s.add_runtime_dependency(%q<ffi>, [">= 0"])
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
-
@@ -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 Version 1, by Geoff Pike and Jyrki Alakuijala
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
- #define UNALIGNED_LOAD64(p) (*(const uint64*)(p))
37
- #define UNALIGNED_LOAD32(p) (*(const uint32*)(p))
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 defined(__GNUC__)
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 = UNALIGNED_LOAD64(s);
78
- uint64 b = UNALIGNED_LOAD64(s + len - 8);
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 = UNALIGNED_LOAD32(s);
83
- return HashLen16(len + (a << 3), UNALIGNED_LOAD32(s + len - 4));
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 = UNALIGNED_LOAD64(s) * k1;
100
- uint64 b = UNALIGNED_LOAD64(s + 8);
101
- uint64 c = UNALIGNED_LOAD64(s + len - 8) * k2;
102
- uint64 d = UNALIGNED_LOAD64(s + len - 16) * k0;
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(UNALIGNED_LOAD64(s),
124
- UNALIGNED_LOAD64(s + 8),
125
- UNALIGNED_LOAD64(s + 16),
126
- UNALIGNED_LOAD64(s + 24),
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 = UNALIGNED_LOAD64(s + 24);
134
- uint64 a = UNALIGNED_LOAD64(s) + (len + UNALIGNED_LOAD64(s + len - 16)) * k0;
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 += UNALIGNED_LOAD64(s + 8);
182
+ a += Fetch64(s + 8);
138
183
  c += Rotate(a, 7);
139
- a += UNALIGNED_LOAD64(s + 16);
184
+ a += Fetch64(s + 16);
140
185
  uint64 vf = a + z;
141
186
  uint64 vs = b + Rotate(a, 31) + c;
142
- a = UNALIGNED_LOAD64(s + 16) + UNALIGNED_LOAD64(s + len - 32);
143
- z = UNALIGNED_LOAD64(s + len - 8);
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 += UNALIGNED_LOAD64(s + len - 24);
191
+ a += Fetch64(s + len - 24);
147
192
  c += Rotate(a, 7);
148
- a += UNALIGNED_LOAD64(s + len - 16);
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 = UNALIGNED_LOAD64(s);
169
- uint64 y = UNALIGNED_LOAD64(s + len - 16) ^ k1;
170
- uint64 z = UNALIGNED_LOAD64(s + len - 56) ^ k0;
171
- pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, y);
172
- pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, len * k1, k0);
173
- z += ShiftMix(v.second) * k1;
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 + UNALIGNED_LOAD64(s + 16), 37) * k1;
181
- y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
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 ^= v.first;
184
- z = Rotate(z ^ w.first, 33);
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 ssize_t. Based on City and Murmur.
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
- ssize_t l = len - 16;
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 = Rotate(a + (len >= 8 ? UNALIGNED_LOAD64(s) : c), 32);
258
+ d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
215
259
  } else { // len > 16
216
- c = HashLen16(UNALIGNED_LOAD64(s + len - 8) + k1, a);
217
- d = HashLen16(b + len, c + UNALIGNED_LOAD64(s + len - 16));
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(UNALIGNED_LOAD64(s) * k1) * k1;
264
+ a ^= ShiftMix(Fetch64(s) * k1) * k1;
221
265
  a *= k1;
222
266
  b ^= a;
223
- c ^= ShiftMix(UNALIGNED_LOAD64(s + 8) * k1) * k1;
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 + UNALIGNED_LOAD64(s);
247
- v.second = Rotate(v.first, 42) * k1 + UNALIGNED_LOAD64(s + 8);
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 + UNALIGNED_LOAD64(s + 88), 53) * k1;
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 + UNALIGNED_LOAD64(s + 16), 37) * k1;
254
- y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
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 ^= v.first;
257
- z = Rotate(z ^ w.first, 33);
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 + UNALIGNED_LOAD64(s + 16), 37) * k1;
263
- y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
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 ^= v.first;
266
- z = Rotate(z ^ w.first, 33);
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(y - x, 42) * k0 + v.second;
279
- w.first += UNALIGNED_LOAD64(s + len - tail_done + 16);
280
- x = Rotate(x, 49) * k0 + w.first;
281
- w.first += v.first;
282
- v = WeakHashLen32WithSeeds(s + len - tail_done, v.first, v.second);
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 48 bytes of state should contain more than
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 48-byte-to-8-byte hashes to get a 16-byte final result.
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(UNALIGNED_LOAD64(s) ^ k3,
298
- UNALIGNED_LOAD64(s + 8)));
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(UNALIGNED_LOAD64(s) ^ (len * k0),
303
- UNALIGNED_LOAD64(s + len - 8) ^ k1));
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
@@ -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 Version 1, by Geoff Pike and Jyrki Alakuijala
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
+ }
@@ -1,12 +1,8 @@
1
1
  require 'mkmf'
2
2
 
3
- have_library('objc') if RUBY_PLATFORM =~ /darwin/
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
- CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/
11
-
12
- create_makefile('cityhash')
8
+ create_makefile('cityhash/cityhash')
@@ -1,63 +1,23 @@
1
- require 'ffi'
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
- module Internal
9
- extend FFI::Library
10
-
11
- ffi_lib(
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.hash64(input, seed1 = nil, seed2 = nil)
30
- input_str = input.to_s
31
-
32
- # Ruby 1.8 compatibility
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
- len = input_str.size
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
@@ -1,12 +1,3 @@
1
1
  module CityHash
2
-
3
- module Version
4
- MAJOR = 0
5
- MINOR = 5
6
- PATCH = 0
7
- BUILD = nil
8
-
9
- STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
10
- end
11
-
2
+ VERSION = "0.6.0"
12
3
  end
@@ -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
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+
4
+ require 'cityhash'
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.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - nashby
8
+ - Vasiliy Ermolovich
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-28 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: ffi
16
- requirement: &24780520 !ruby/object:Gem::Requirement
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
- - .document
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/city_ruby_bridge.cpp
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/helper.rb
104
- - test/test_cityhash.rb
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: -4372501756799673446
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.6
62
+ rubyforge_project: cityhash
63
+ rubygems_version: 1.8.19
130
64
  signing_key:
131
65
  specification_version: 3
132
- summary: ffi wrapper for google's cityhash
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
@@ -1,5 +0,0 @@
1
- lib/**/*.rb
2
- bin/*
3
- -
4
- features/**/*.feature
5
- LICENSE.txt
@@ -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);
@@ -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
@@ -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