murmur_redux 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f86efa1d0a92c333ab5119703d1be96f108cd342
4
- data.tar.gz: c775a8a518c9d285a4919ef30843fc9b69116e7d
3
+ metadata.gz: 925117d747be38f53fff1621f2b2a5c50ff81843
4
+ data.tar.gz: 2f56e116c367da28c0d039fcfb43ce6a082ce84b
5
5
  SHA512:
6
- metadata.gz: 5da0aff8b1c40090d1d96144c53cf50347c3307753db3849c78f1a05b2498ab5bb86723e79a15b1b4f31cb6cbb05490c49ac88f160200795eb75f51fdc5a7199
7
- data.tar.gz: 603bcefa464c6e311839c8365443ca2c13a29414c7c79c3515b892318980fc6bc2b098b8f3c79f76ae5b894f0599974d3162bbffdefb46379ad8aa4614ea5c5e
6
+ metadata.gz: af1fffda69050fd8a3d9290622c6a1fa2024fd0d0097e273ca9409aebbfb116f48f11e1bd45295098aad07ee850f1c0598e062ec28f2c8e3502eca65eff24d1c
7
+ data.tar.gz: 6acbb6e828d76d3f2bdef8dd9b25180d32145426c2d2d009af4ca8ab25f31d67437290aad20a9f2dfcf8996ed4313fe3a1f8ade0cbe74791dbbd72a2fd0933be
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.gem
2
2
  *.swp
3
3
  *.lock
4
+ *.so
4
5
  tmp/*
data/.rspec CHANGED
File without changes
data/.ruby-gemset CHANGED
File without changes
data/.ruby-version CHANGED
File without changes
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :test do
6
+ gem 'rake-compiler'
6
7
  gem 'rspec'
7
8
  gem 'guard-rspec'
8
9
  end
data/Guardfile CHANGED
File without changes
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
- # Search redux
1
+ # Murmur redux
2
2
 
3
3
  A simpler wrapper around [murmurhash3](https://github.com/funny-falcon/murmurhash3-ruby) gem with a nicer API.
4
4
 
5
- ## Requirements
6
-
7
- Murmur redux requires at least Ruby >= 1.9.2
5
+ It defaults to `MurmurHash3_x86_128` which is a nice combination of low latency and with good collision resistence.
8
6
 
9
7
  ## Installation
10
8
 
@@ -19,12 +17,33 @@ gem 'murmur_redux'
19
17
  By default it uses MurmurHash3_x86_128 which is a nice combination of low latency and with good collision resistence.
20
18
 
21
19
  ```ruby
22
- class MyClass
23
- hex_string = MurmurRedux::Hash.digest('test')
24
- end
20
+ hex_string = MurmurRedux::Hash.digest('test')
21
+
22
+ # => '9de1bd74cc287dac824dbdf93182129a'
25
23
  ```
26
24
 
27
- ## License (MIT)
25
+ ### FAQ
26
+
27
+ ##### What is MurmurHash ?
28
+
29
+ From its Wikipedia page[0] :
30
+
31
+ >MurmurHash is a non-cryptographic hash function suitable for general hash-based lookup. It was created by Austin Appleby in 2008, and exists in a number of variants, all of which have been released into the public domain. When compared to other popular hash functions, MurmurHash performed well in a random distribution of regular keys.
32
+
33
+ ##### How fast is it ?
34
+
35
+ Is one of the fastest hashing algorithms with with good to great collision resistence[1].
36
+
37
+ - [0] - [wiki article](http://en.wikipedia.org/wiki/MurmurHash)
38
+ - [1] - [performance](http://programmers.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed)
39
+
40
+ ### Credits
41
+
42
+ - [MurmurHash3](https://code.google.com/p/smhasher/wiki/MurmurHash3)
43
+ - [murmurhash3-ruby gem](https://github.com/funny-falcon/murmurhash3-ruby)
44
+ - [Byte Friendly article on MurmurHash 3](http://tech.tulentsev.com/2012/10/ruby-gem-for-murmurhash-3)
45
+
46
+ ### License (MIT)
28
47
 
29
48
  Copyright (c) 2013 Marian Posaceanu
30
49
 
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+ require 'rake/extensiontask'
6
+
7
+ Rake::ExtensionTask.new 'murmur_native' do |ext|
8
+ ext.lib_dir = 'lib/murmur_redux'
9
+ end
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('murmur_native')
@@ -0,0 +1,467 @@
1
+ #include <ruby.h>
2
+ /*-----------------------------------------------------------------------------
3
+ * MurmurHash3 was written by Austin Appleby, and is placed in the public
4
+ * domain. The author hereby disclaims copyright to this source code.
5
+
6
+ * Note - The x86 and x64 versions do _not_ produce the same results, as the
7
+ * algorithms are optimized for their respective platforms. You can still
8
+ * compile and run any of them on any platform, but your performance with the
9
+ * non-native version will be less than optimal.
10
+ */
11
+
12
+ typedef unsigned char uint8_t;
13
+ typedef unsigned int uint32_t;
14
+ #ifndef HAVE_STDINT_H
15
+ #if SIZEOF_LONG == 8
16
+ typedef unsigned long uint64_t;
17
+ #else
18
+ typedef unsigned long long uint64_t;
19
+ #endif
20
+ #endif
21
+
22
+ /*-----------------------------------------------------------------------------
23
+ * Platform-specific functions and macros
24
+ */
25
+
26
+ #ifdef __GNUC__
27
+ #define FORCE_INLINE __attribute__((always_inline))
28
+ #elif defined(_MSC_VER)
29
+ #define FORCE_INLINE __forceinline
30
+ #else
31
+ #define FORCE_INLINE
32
+ #endif
33
+
34
+ #if defined(_MSC_VER)
35
+
36
+ #define ROTL32(x,y) _rotl(x,y)
37
+ #define ROTL64(x,y) _rotl64(x,y)
38
+
39
+ #define BIG_CONSTANT(x) (x)
40
+
41
+ #else
42
+
43
+ static inline FORCE_INLINE uint32_t
44
+ rotl32 ( uint32_t x, int8_t r )
45
+ {
46
+ return (x << r) | (x >> (32 - r));
47
+ }
48
+
49
+ static inline FORCE_INLINE uint64_t
50
+ rotl64 ( uint64_t x, int8_t r )
51
+ {
52
+ return (x << r) | (x >> (64 - r));
53
+ }
54
+
55
+ #define ROTL32(x,y) rotl32(x,y)
56
+ #define ROTL64(x,y) rotl64(x,y)
57
+
58
+ #define BIG_CONSTANT(x) (x##LLU)
59
+ #endif
60
+
61
+ /* end platform specific */
62
+
63
+ /* Block read - if your platform needs to do endian-swapping or can only
64
+ * handle aligned reads, do the conversion here */
65
+ #ifdef WORDS_BIGENDIAN
66
+ #define GCC_VERSION_SINCE(major, minor, patchlevel) \
67
+ (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
68
+ ((__GNUC__ > (major)) || \
69
+ (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
70
+ (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
71
+ #if GCC_VERSION_SINCE(4,3,0)
72
+ # define swap32(x) __builtin_bswap32(x)
73
+ # define swap64(x) __builtin_bswap64(x)
74
+ #endif
75
+
76
+ #ifndef swap32
77
+ # define swap32(x) ((((x)&0xFF)<<24) \
78
+ |(((x)>>24)&0xFF) \
79
+ |(((x)&0x0000FF00)<<8) \
80
+ |(((x)&0x00FF0000)>>8) )
81
+ #endif
82
+
83
+ #ifndef swap64
84
+ # ifdef HAVE_INT64_T
85
+ static inline FORCE_INLINE uint64_t
86
+ swap64(uint64_t x) {
87
+ x = (x>>32) | (x << 32);
88
+ x = ((x & BIG_CONSTANT(0xFFFF0000FFFF0000)) >> 16) |
89
+ ((x & BIG_CONSTANT(0x0000FFFF0000FFFF)) << 16);
90
+ return ((x & BIG_CONSTANT(0xFF00FF00FF00FF00)) >> 8) |
91
+ ((x & BIG_CONSTANT(0x00FF00FF00FF00FF)) << 8);
92
+ }
93
+ # endif
94
+
95
+ #endif
96
+ static inline FORCE_INLINE uint32_t
97
+ getblock32(const uint32_t * p, int i)
98
+ {
99
+ return swap32(p[i]);
100
+ }
101
+
102
+ static inline FORCE_INLINE uint64_t
103
+ getblock64(const uint64_t * p, int i)
104
+ {
105
+ return swap64(p[i]);
106
+ }
107
+ #else
108
+ #define getblock32(p, i) (p[i])
109
+ #define getblock64(p, i) (p[i])
110
+ #endif
111
+
112
+ /* Finalization mix - force all bits of a hash block to avalanche */
113
+
114
+ static inline FORCE_INLINE uint32_t
115
+ fmix32 ( uint32_t h )
116
+ {
117
+ h ^= h >> 16;
118
+ h *= 0x85ebca6b;
119
+ h ^= h >> 13;
120
+ h *= 0xc2b2ae35;
121
+ h ^= h >> 16;
122
+
123
+ return h;
124
+ }
125
+
126
+ static inline FORCE_INLINE uint64_t
127
+ fmix64 ( uint64_t k )
128
+ {
129
+ k ^= k >> 33;
130
+ k *= BIG_CONSTANT(0xff51afd7ed558ccd);
131
+ k ^= k >> 33;
132
+ k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
133
+ k ^= k >> 33;
134
+
135
+ return k;
136
+ }
137
+
138
+ static inline FORCE_INLINE uint32_t
139
+ mmix32(uint32_t k1)
140
+ {
141
+ k1 *= 0xcc9e2d51;
142
+ k1 = ROTL32(k1, 15);
143
+ return k1 * 0x1b873593;
144
+ }
145
+
146
+ static uint32_t
147
+ MurmurHash3_x86_32 ( const void * key, long len, uint32_t seed)
148
+ {
149
+ const uint8_t * data = (const uint8_t*)key;
150
+ const int nblocks = (int)(len / 4);
151
+ int i;
152
+
153
+ uint32_t h1 = seed;
154
+ uint32_t k1 = 0;
155
+
156
+
157
+ /* body */
158
+
159
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
160
+
161
+ for(i = -nblocks; i; i++)
162
+ {
163
+ h1 ^= mmix32(getblock32(blocks, i));
164
+ h1 = ROTL32(h1,13);
165
+ h1 = h1*5+0xe6546b64;
166
+ }
167
+
168
+ /* tail */
169
+
170
+ data += nblocks*4;
171
+
172
+ switch(len & 3)
173
+ {
174
+ case 3: k1 ^= data[2] << 16;
175
+ case 2: k1 ^= data[1] << 8;
176
+ case 1: k1 ^= data[0];
177
+ h1 ^= mmix32(k1);
178
+ };
179
+
180
+ /* finalization */
181
+
182
+ h1 ^= len;
183
+
184
+ h1 = fmix32(h1);
185
+
186
+ return h1;
187
+ }
188
+
189
+ #define C1_128 BIG_CONSTANT(0x87c37b91114253d5)
190
+ #define C2_128 BIG_CONSTANT(0x4cf5ad432745937f)
191
+
192
+ static inline FORCE_INLINE uint64_t
193
+ mmix128_1(uint64_t k1)
194
+ {
195
+ k1 *= C1_128;
196
+ k1 = ROTL64(k1, 31);
197
+ return k1 * C2_128;
198
+ }
199
+
200
+ static inline FORCE_INLINE uint64_t
201
+ mmix128_2(uint64_t k2)
202
+ {
203
+ k2 *= C2_128;
204
+ k2 = ROTL64(k2, 33);
205
+ return k2 * C1_128;
206
+ }
207
+
208
+ static void MurmurHash3_x64_128 ( const void * key, const long len,
209
+ const uint32_t seed, void * out )
210
+ {
211
+ const uint8_t * data = (const uint8_t*)key;
212
+ const int nblocks = (int)(len / 16);
213
+ int i;
214
+
215
+ uint64_t h1 = seed;
216
+ uint64_t h2 = seed;
217
+ uint64_t k1 = 0, k2 = 0;
218
+
219
+ /* body */
220
+
221
+ const uint64_t * blocks = (const uint64_t *)(data);
222
+
223
+ for(i = 0; i < nblocks; i++)
224
+ {
225
+ k1 = getblock64(blocks, i*2+0);
226
+ k2 = getblock64(blocks, i*2+1);
227
+
228
+ h1 ^= mmix128_1(k1);
229
+ h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
230
+
231
+ h2 ^= mmix128_2(k2);
232
+ h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
233
+ }
234
+
235
+ /* tail */
236
+
237
+ data += nblocks*16;
238
+ k1 = k2 = 0;
239
+
240
+ switch(len & 15)
241
+ {
242
+ case 15: k2 ^= (uint64_t)(data[14]) << 48;
243
+ case 14: k2 ^= (uint64_t)(data[13]) << 40;
244
+ case 13: k2 ^= (uint64_t)(data[12]) << 32;
245
+ case 12: k2 ^= (uint64_t)(data[11]) << 24;
246
+ case 11: k2 ^= (uint64_t)(data[10]) << 16;
247
+ case 10: k2 ^= (uint64_t)(data[ 9]) << 8;
248
+ case 9: k2 ^= (uint64_t)(data[ 8]) << 0;
249
+ h2 ^= mmix128_2(k2);
250
+
251
+ case 8: k1 ^= (uint64_t)(data[ 7]) << 56;
252
+ case 7: k1 ^= (uint64_t)(data[ 6]) << 48;
253
+ case 6: k1 ^= (uint64_t)(data[ 5]) << 40;
254
+ case 5: k1 ^= (uint64_t)(data[ 4]) << 32;
255
+ case 4: k1 ^= (uint64_t)(data[ 3]) << 24;
256
+ case 3: k1 ^= (uint64_t)(data[ 2]) << 16;
257
+ case 2: k1 ^= (uint64_t)(data[ 1]) << 8;
258
+ case 1: k1 ^= (uint64_t)(data[ 0]) << 0;
259
+ h1 ^= mmix128_1(k1);
260
+ };
261
+
262
+ /* finalization */
263
+
264
+ h1 ^= len; h2 ^= len;
265
+
266
+ h1 += h2;
267
+ h2 += h1;
268
+
269
+ h1 = fmix64(h1);
270
+ h2 = fmix64(h2);
271
+
272
+ h1 += h2;
273
+ h2 += h1;
274
+
275
+ ((uint64_t*)out)[0] = h1;
276
+ ((uint64_t*)out)[1] = h2;
277
+ }
278
+
279
+ /* end of MurmurHash3 algorithm */
280
+
281
+ static VALUE
282
+ rb_fmix32(VALUE self, VALUE integer)
283
+ {
284
+ uint32_t _int = NUM2UINT(integer);
285
+ return UINT2NUM(fmix32(_int));
286
+ }
287
+
288
+ static VALUE
289
+ rb_fmix64(VALUE self, VALUE integer)
290
+ {
291
+ #if SIZEOF_LONG == 8
292
+ uint64_t _int = NUM2ULONG(integer);
293
+ return ULONG2NUM(fmix64(_int));
294
+ #else
295
+ uint64_t _int = NUM2ULL(integer);
296
+ return ULL2NUM(fmix64(_int));
297
+ #endif
298
+ }
299
+
300
+ static VALUE
301
+ rb_murmur3_32_str_hash(int argc, VALUE* argv, VALUE self)
302
+ {
303
+ VALUE rstr;
304
+ uint32_t result;
305
+
306
+ if (argc == 0 || argc > 2) {
307
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (string[, seed])");
308
+ }
309
+ rstr = argv[0];
310
+ StringValue(rstr);
311
+
312
+ result = MurmurHash3_x86_32(RSTRING_PTR(rstr), RSTRING_LEN(rstr), argc == 1 ? 0 : NUM2UINT(argv[1]));
313
+
314
+ return UINT2NUM(result);
315
+ }
316
+
317
+ static VALUE
318
+ rb_murmur3_32_int32_hash(int argc, VALUE* argv, VALUE self)
319
+ {
320
+ /* VALUE rint; */
321
+ uint32_t _int;
322
+ uint32_t result;
323
+
324
+ if (argc == 0 || argc > 2) {
325
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (int32[, seed])");
326
+ }
327
+ _int = NUM2UINT(argv[0]);
328
+
329
+ result = MurmurHash3_x86_32(&_int, 4, argc == 1 ? 0 : NUM2UINT(argv[1]));
330
+
331
+ return UINT2NUM(result);
332
+ }
333
+
334
+ static VALUE
335
+ rb_murmur3_32_int64_hash(int argc, VALUE* argv, VALUE self)
336
+ {
337
+ /* VALUE rint; */
338
+ uint64_t _int;
339
+ uint32_t result;
340
+
341
+ if (argc == 0 || argc > 2) {
342
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (int64[, seed])");
343
+ }
344
+ #if SIZEOF_LONG == 8
345
+ _int = NUM2ULONG(argv[0]);
346
+ #else
347
+ _int = NUM2ULL(argv[0]);
348
+ #endif
349
+
350
+ result = MurmurHash3_x86_32(&_int, 8, argc == 1 ? 0 : NUM2UINT(argv[1]));
351
+
352
+ return UINT2NUM(result);
353
+ }
354
+
355
+ #define PREPARE_128_BIT() \
356
+ VALUE rstr, rseed, ar_result; \
357
+ uint32_t result[4]; \
358
+
359
+ #define SWAP_128_BIT() do { \
360
+ uint32_t tmp; \
361
+ tmp = result[0]; \
362
+ result[0] = result[1]; \
363
+ result[1] = tmp; \
364
+ tmp = result[2]; \
365
+ result[2] = result[3]; \
366
+ result[3] = tmp; \
367
+ } while (0)
368
+
369
+ #define RETURN_128_BIT() \
370
+ ar_result = rb_ary_new2(4); \
371
+ rb_ary_push(ar_result, UINT2NUM(result[0])); \
372
+ rb_ary_push(ar_result, UINT2NUM(result[1])); \
373
+ rb_ary_push(ar_result, UINT2NUM(result[2])); \
374
+ rb_ary_push(ar_result, UINT2NUM(result[3])); \
375
+ return ar_result
376
+
377
+ static VALUE
378
+ rb_murmur3_128_str_hash(int argc, VALUE* argv, VALUE self)
379
+ {
380
+ VALUE rstr, ar_result;
381
+ uint32_t result[4];
382
+
383
+ if (argc == 0 || argc > 2) {
384
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (string[, seed])");
385
+ }
386
+ rstr = argv[0];
387
+ StringValue(rstr);
388
+
389
+ MurmurHash3_x64_128(RSTRING_PTR(rstr), RSTRING_LEN(rstr), argc == 1 ? 0 : NUM2UINT(argv[1]), result);
390
+ #if WORDS_BIGENDIAN
391
+ SWAP_128_BIT();
392
+ #endif
393
+ RETURN_128_BIT();
394
+ }
395
+
396
+ static VALUE
397
+ rb_murmur3_128_int32_hash(int argc, VALUE* argv, VALUE self)
398
+ {
399
+ VALUE ar_result;
400
+ uint32_t result[4], _int;
401
+
402
+ if (argc == 0 || argc > 2) {
403
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (int32[, seed])");
404
+ }
405
+ _int = NUM2UINT(argv[0]);
406
+ MurmurHash3_x64_128(&_int, 4, argc == 1 ? 0 : NUM2UINT(argv[1]), result);
407
+ #if WORDS_BIGENDIAN
408
+ SWAP_128_BIT();
409
+ #endif
410
+ RETURN_128_BIT();
411
+ }
412
+
413
+ static VALUE
414
+ rb_murmur3_128_int64_hash(int argc, VALUE* argv, VALUE self)
415
+ {
416
+ VALUE ar_result;
417
+ uint32_t result[4];
418
+ uint64_t _int;
419
+
420
+ if (argc == 0 || argc > 2) {
421
+ rb_raise(rb_eArgError, "accept 1 or 2 arguments: (int64[, seed])");
422
+ }
423
+ #if SIZEOF_LONG == 8
424
+ _int = NUM2ULONG(argv[0]);
425
+ #else
426
+ _int = NUM2ULL(argv[0]);
427
+ #endif
428
+ MurmurHash3_x64_128(&_int, 8, argc == 1 ? 0 : NUM2UINT(argv[1]), result);
429
+ #if WORDS_BIGENDIAN
430
+ SWAP_128_BIT();
431
+ #endif
432
+ RETURN_128_BIT();
433
+ }
434
+
435
+ void
436
+ Init_murmur_native() {
437
+ VALUE singleton;
438
+ VALUE mod_murmur = rb_define_module("MurmurRedux");
439
+ VALUE mod_murmur32 = rb_define_module_under(mod_murmur, "Native32");
440
+ VALUE mod_murmur128 = rb_define_module_under(mod_murmur, "Native128");
441
+
442
+ rb_define_method(mod_murmur32, "murmur3_32_fmix", rb_fmix32, 1);
443
+ rb_define_method(mod_murmur32, "murmur3_32_str_hash", rb_murmur3_32_str_hash, -1);
444
+ rb_define_method(mod_murmur32, "murmur3_32_int32_hash", rb_murmur3_32_int32_hash, -1);
445
+ rb_define_method(mod_murmur32, "murmur3_32_int64_hash", rb_murmur3_32_int64_hash, -1);
446
+
447
+ rb_extend_object(mod_murmur32, mod_murmur32);
448
+ singleton = rb_singleton_class(mod_murmur32);
449
+ rb_define_alias(singleton, "fmix", "murmur3_32_fmix");
450
+ rb_define_alias(singleton, "str_hash", "murmur3_32_str_hash");
451
+ rb_define_alias(singleton, "int32_hash", "murmur3_32_int32_hash");
452
+ rb_define_alias(singleton, "int64_hash", "murmur3_32_int64_hash");
453
+
454
+
455
+ rb_define_method(mod_murmur128, "murmur3_128_fmix", rb_fmix64, 1);
456
+ rb_define_method(mod_murmur128, "murmur3_128_str_hash", rb_murmur3_128_str_hash, -1);
457
+ rb_define_method(mod_murmur128, "murmur3_128_int32_hash", rb_murmur3_128_int32_hash, -1);
458
+ rb_define_method(mod_murmur128, "murmur3_128_int64_hash", rb_murmur3_128_int64_hash, -1);
459
+
460
+ rb_extend_object(mod_murmur128, mod_murmur128);
461
+ singleton = rb_singleton_class(mod_murmur128);
462
+ rb_define_alias(singleton, "fmix", "murmur3_128_fmix");
463
+ rb_define_alias(singleton, "str_hash", "murmur3_128_str_hash");
464
+ rb_define_alias(singleton, "int32_hash", "murmur3_128_int32_hash");
465
+ rb_define_alias(singleton, "int64_hash", "murmur3_128_int64_hash");
466
+
467
+ }
File without changes
@@ -2,14 +2,14 @@ module MurmurRedux
2
2
  class Hash
3
3
  class << self
4
4
  def digest(string)
5
- ints = MurmurHash3::V128.str_hash(string)
5
+ ints = MurmurRedux::V128.str_hash(string)
6
6
 
7
- gen_hex_string(ints)
7
+ generate_hex_string(ints)
8
8
  end
9
9
 
10
10
  private
11
11
 
12
- def gen_hex_string(ints)
12
+ def generate_hex_string(ints)
13
13
  ints.pack('L*').unpack('H*').first
14
14
  end
15
15
  end
@@ -1,3 +1,3 @@
1
1
  module MurmurRedux
2
- VERSION = '0.0.1' unless defined? MurmurRedux::VERSION
2
+ VERSION = '1.0.0' unless defined? MurmurRedux::VERSION
3
3
  end
data/lib/murmur_redux.rb CHANGED
@@ -1,6 +1,9 @@
1
- require 'murmurhash3'
1
+ module MurmurRedux
2
+ require 'murmur_redux/murmur_native'
3
+ V32 = Native32
4
+ V128 = Native128
5
+ end
2
6
 
3
7
  require 'murmur_redux/version'
4
8
  require 'murmur_redux/errors'
5
9
  require 'murmur_redux/hash'
6
-
data/murmur_redux.gemspec CHANGED
@@ -1,20 +1,21 @@
1
- $LOAD_PATH.push File.expand_path("../lib", __FILE__)
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+ require 'rake'
2
3
  require 'murmur_redux/version'
3
4
 
4
- Gem::Specification.new do |s|
5
- s.name = 'murmur_redux'
6
- s.version = MurmurRedux::VERSION
7
- s.platform = Gem::Platform::RUBY
8
- s.summary = 'A simple wrapper around murmurhash3 gem with a nicer API.'
9
- s.description = 'A simple wrapper around murmurhash3 gem with a nicer API : MurmurRedux::Hash.digest(string)'
10
- s.author = 'Marian Posaceanu'
11
- s.email = 'contact@marianposaceanu.com'
12
- s.files = `git ls-files`.split("\n")
13
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
- s.require_paths = ['lib']
15
- s.homepage = 'https://github.com/dakull/murmur_redux'
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'murmur_redux'
7
+ gem.version = MurmurRedux::VERSION
8
+ gem.platform = Gem::Platform::RUBY
9
+ gem.summary = 'A simple wrapper around murmurhash3 C extension.'
10
+ gem.description = 'A simple wrapper around murmurhash3 C extension originally based on https://github.com/funny-falcon/murmurhash3-ruby'
11
+ gem.author = 'Marian Posaceanu'
12
+ gem.email = 'contact@marianposaceanu.com'
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ gem.require_paths = ['lib', 'ext']
16
+ gem.homepage = 'https://github.com/dakull/murmur_redux'
17
+ gem.extensions = FileList["ext/**/extconf.rb"]
18
+ gem.license = 'MIT'
16
19
 
17
- s.required_ruby_version = '>= 1.9.2'
18
-
19
- s.add_dependency('murmurhash3', '~> 0.1.3')
20
+ gem.required_ruby_version = '>= 1.9.2'
20
21
  end
@@ -0,0 +1,55 @@
1
+ shared_examples_128 = proc do
2
+ it 'should make correct hash for string' do
3
+ murmur.str_hash('asdfqwer', 0).should eq([0xd6d7d367, 0xcb41f064, 0x8973cd72, 0xc345e72e])
4
+ murmur.str_hash('asdfqwerzxcvyui', 0).should eq([0x007b2172f, 0x64ecae1b, 0x1813b5a5, 0x9c674ee6])
5
+ murmur.str_hash('asdfqwerzxcvyuio', 0).should eq([0xf508df57, 0xbb38f3fd, 0xf48c9d98, 0xb65c36cd])
6
+ murmur.str_hash('asdfqwerzxcvyuio!', 0).should eq([0x8a011755, 0xb13d463f, 0x8386d32a, 0x0df8884c])
7
+ end
8
+
9
+ it 'should make correct hash for 32bit integer' do
10
+ murmur.int32_hash(1717859169).should eq([0x20b48108, 0x10369ceb, 0x3ad523cc, 0xdacb587f])
11
+ murmur.int32_hash(1717859169).should eq(murmur.str_hash('asdf'))
12
+ end
13
+
14
+ it 'should make correct hash for 64bit integer' do
15
+ murmur.int64_hash(0x12345678).should eq(murmur.str_hash("\x78\x56\x34\x12\x00\x00\x00\x00"))
16
+ murmur.int64_hash(0x1234567812345678).should eq(murmur.str_hash("\x78\x56\x34\x12\x78\x56\x34\x12"))
17
+ end
18
+
19
+ it 'should make correct fmix for 64bit integer' do
20
+ murmur.fmix(1717859169).should eq(0xbefb9076a3712207)
21
+ murmur.fmix(12345678912345678).should eq(0x197ef59146f5221c)
22
+ end
23
+ end
24
+
25
+ shared_examples_32 = proc do
26
+ it 'should make correct hash for string' do
27
+ murmur.str_hash('asdfqwer', 0).should eq(0xa46b5209)
28
+ murmur.str_hash('asdfqwerty', 0).should eq(0xa3cfe04b)
29
+ murmur.str_hash('asd', 0).should eq(0x14570c6f)
30
+ end
31
+
32
+ it 'should make correct hash for 32bit integer' do
33
+ murmur.int32_hash(1717859169).should eq(0x1b20e026)
34
+ murmur.int32_hash(1717859169).should eq(murmur.str_hash('asdf'))
35
+ end
36
+
37
+ it 'should make correct hash for 64bit integer' do
38
+ murmur.int64_hash(0x12345678).should eq(murmur.str_hash("\x78\x56\x34\x12\x00\x00\x00\x00"))
39
+ murmur.int64_hash(0x1234567812345678).should eq(murmur.str_hash("\x78\x56\x34\x12\x78\x56\x34\x12"))
40
+ end
41
+
42
+ it 'should make correct fmix for 32bit integer' do
43
+ murmur.fmix(1717859169).should eq(0x17561734)
44
+ end
45
+ end
46
+
47
+ describe "Native 32" do
48
+ let(:murmur) { MurmurRedux::Native32 }
49
+ class_exec &shared_examples_32
50
+ end
51
+
52
+ describe "Native 128" do
53
+ let(:murmur) { MurmurRedux::Native128 }
54
+ class_exec &shared_examples_128
55
+ end
@@ -6,6 +6,6 @@ describe MurmurRedux::Hash do
6
6
  it 'digests an argument supplied string into a hexadecimal representation' do
7
7
  digested_string = MurmurRedux::Hash.digest(string_to_digest)
8
8
 
9
- expect(digested_string).should eq('df65d6d2d12d51f164c5f3a85066322c')
9
+ expect(digested_string).to eq('df65d6d2d12d51f164c5f3a85066322c')
10
10
  end
11
11
  end
data/spec/spec_helper.rb CHANGED
File without changes
metadata CHANGED
@@ -1,33 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: murmur_redux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marian Posaceanu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-08 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: murmurhash3
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: 0.1.3
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: 0.1.3
27
- description: 'A simple wrapper around murmurhash3 gem with a nicer API : MurmurRedux::Hash.digest(string)'
11
+ date: 2013-09-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple wrapper around murmurhash3 C extension originally based on https://github.com/funny-falcon/murmurhash3-ruby
28
14
  email: contact@marianposaceanu.com
29
15
  executables: []
30
- extensions: []
16
+ extensions:
17
+ - ext/murmur_native/extconf.rb
31
18
  extra_rdoc_files: []
32
19
  files:
33
20
  - .gitignore
@@ -37,20 +24,26 @@ files:
37
24
  - Gemfile
38
25
  - Guardfile
39
26
  - README.md
27
+ - Rakefile
28
+ - ext/murmur_native/extconf.rb
29
+ - ext/murmur_native/murmur_native.c
40
30
  - lib/murmur_redux.rb
41
31
  - lib/murmur_redux/errors.rb
42
32
  - lib/murmur_redux/hash.rb
43
33
  - lib/murmur_redux/version.rb
44
34
  - murmur_redux.gemspec
35
+ - spec/murmur_native_spec.rb
45
36
  - spec/murmur_redux/hash_spec.rb
46
37
  - spec/spec_helper.rb
47
38
  homepage: https://github.com/dakull/murmur_redux
48
- licenses: []
39
+ licenses:
40
+ - MIT
49
41
  metadata: {}
50
42
  post_install_message:
51
43
  rdoc_options: []
52
44
  require_paths:
53
45
  - lib
46
+ - ext
54
47
  required_ruby_version: !ruby/object:Gem::Requirement
55
48
  requirements:
56
49
  - - '>='
@@ -63,8 +56,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
56
  version: '0'
64
57
  requirements: []
65
58
  rubyforge_project:
66
- rubygems_version: 2.0.0
59
+ rubygems_version: 2.0.3
67
60
  signing_key:
68
61
  specification_version: 4
69
- summary: A simple wrapper around murmurhash3 gem with a nicer API.
62
+ summary: A simple wrapper around murmurhash3 C extension.
70
63
  test_files: []