Skip to content

Commit

Permalink
add crc methods
Browse files Browse the repository at this point in the history
  • Loading branch information
nashby committed Apr 27, 2013
1 parent e2acc70 commit 1089505
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,8 @@
## Unreleased ##

### enhancements
* add crc methods

## 0.7.0 (October 25, 2012) ##

### enhancements
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -21,6 +21,8 @@ CityHash.hash64(text, seed1) # => 9154302171269876511
CityHash.hash64(text, seed1, seed2) # => 4854399283587686019
CityHash.hash128(text) # => 124124989950401219618153994964897029896
CityHash.hash128(text, seed1) # => 101668641288246442316643001405184598611
CityHash.hash128crc(text) # => 124124989950401219618153994964897029896
CityHash.hash128crc(text, seed1) # => 101668641288246442316643001405184598611
```

### Contributing to cityhash
Expand Down
43 changes: 43 additions & 0 deletions ext/cityhash/citycrc.h
@@ -0,0 +1,43 @@
// Copyright (c) 2011 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// CityHash, by Geoff Pike and Jyrki Alakuijala
//
// This file declares the subset of the CityHash functions that require
// _mm_crc32_u64(). See the CityHash README for details.
//
// Functions in the CityHash family are not suitable for cryptography.

#ifndef CITY_HASH_CRC_H_
#define CITY_HASH_CRC_H_

#include <city.h>

// Hash function for a byte array.
uint128 CityHashCrc128(const char *s, size_t len);

// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed);

// Hash function for a byte array. Sets result[0] ... result[3].
void CityHashCrc256(const char *s, size_t len, uint64 *result);

#endif // CITY_HASH_CRC_H_
24 changes: 24 additions & 0 deletions ext/cityhash/cityhash.cc
@@ -1,6 +1,10 @@
#include <ruby.h>
#include "city.h"

#ifdef __SSE4_2__
#include "citycrc.h"
#endif

// Use this typedef to make the compiler happy when
// calling rb_define_method()
typedef VALUE (ruby_method)(...);
Expand Down Expand Up @@ -38,6 +42,21 @@ extern "C" VALUE cityhash_hash128_with_seed(VALUE mod, VALUE input, VALUE seed_s
return rb_str_new((char *)&hash, sizeof(hash));
}

#ifdef __SSE4_2__
extern "C" VALUE cityhash_hashcrc128(VALUE mod, VALUE input)
{
uint128 hash = CityHashCrc128(StringValuePtr(input), RSTRING_LEN(input));
return rb_str_new((char *)&hash, sizeof(hash));
}

extern "C" VALUE cityhash_hashcrc128_with_seed(VALUE mod, VALUE input, VALUE seed_string)
{
uint128 seed = *(uint128 *)StringValuePtr(seed_string);
uint128 hash = CityHashCrc128WithSeed(StringValuePtr(input), RSTRING_LEN(input), seed);
return rb_str_new((char *)&hash, sizeof(hash));
}
#endif

extern "C" void Init_cityhash()
{
VALUE mCityHash = rb_define_module("CityHash");
Expand All @@ -51,4 +70,9 @@ extern "C" void Init_cityhash()

rb_define_singleton_method(mInternal, "hash128", (ruby_method*) &cityhash_hash128, 1);
rb_define_singleton_method(mInternal, "hash128_with_seed", (ruby_method*) &cityhash_hash128_with_seed, 2);

#ifdef __SSE4_2__
rb_define_singleton_method(mInternal, "hash128crc", (ruby_method*) &cityhash_hashcrc128, 1);
rb_define_singleton_method(mInternal, "hash128crc_with_seed", (ruby_method*) &cityhash_hashcrc128_with_seed, 2);
#endif
}
2 changes: 1 addition & 1 deletion ext/cityhash/extconf.rb
@@ -1,6 +1,6 @@
require 'mkmf'

%w{g O3 Wall}.each do |flag|
%w{g O3 Wall msse4.2}.each do |flag|
flag = "-#{flag}"
$CPPFLAGS += " #{flag}" unless $CPPFLAGS.split.include? flag
end
Expand Down
28 changes: 24 additions & 4 deletions lib/cityhash.rb
Expand Up @@ -16,12 +16,32 @@ def self.hash64(input, seed1=nil, seed2=nil)
end

def self.hash128(input, seed=nil)
if seed
seed = [seed & LOW64_MASK, seed & HIGH64_MASK >> 64].pack('QQ')
digest = Internal.hash128_with_seed(input, seed)
digest = if seed
Internal.hash128_with_seed(input, packed_seed(seed))
else
digest = Internal.hash128(input)
Internal.hash128(input)
end

unpacked_digest(digest)
end

def self.hash128crc(input, seed=nil)
digest = if seed
Internal.hash128crc_with_seed(input, packed_seed(seed))
else
Internal.hash128crc(input)
end

unpacked_digest(digest)
end

private

def self.packed_seed(seed)
[seed & LOW64_MASK, seed & HIGH64_MASK >> 64].pack('QQ')
end

def self.unpacked_digest(digest)
[0..7, 8..15].map { |r| digest[r].unpack('Q').first.to_s }.join.to_i
end
end
9 changes: 9 additions & 0 deletions test/cityhash_test.rb
Expand Up @@ -25,4 +25,13 @@
seed = (123 << 64) | 123
assert_equal 1834994000056895780313918994795281207519, CityHash.hash128("test", seed)
end

it "returns 128bit crc hash" do
assert_equal 124124989950401219618153994964897029896, CityHash.hash128crc("test")
end

it "returns 128bit crc hash with seed" do
seed = (123 << 64) | 123
assert_equal 1834994000056895780313918994795281207519, CityHash.hash128crc("test", seed)
end
end

0 comments on commit 1089505

Please sign in to comment.