google_hash 0.5.1 → 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.
- data/README +39 -14
- data/VERSION +1 -1
- data/ext/extconf.rb +23 -13
- data/ext/temp/extconf.rb +11 -0
- data/ext/template/google_hash.cpp.erb +37 -9
- data/spec/spec.google_hash.rb +40 -17
- metadata +6 -4
data/README
CHANGED
@@ -28,26 +28,51 @@ See also the results.txt file
|
|
28
28
|
|
29
29
|
Usage:
|
30
30
|
|
31
|
-
a = GoogleHashDenseRubyToRuby.new
|
32
|
-
b = GoogleHashDenseIntToRuby.new # :int => Ruby
|
31
|
+
a = GoogleHashDenseRubyToRuby.new # like a normal Ruby hash, with slightly different performance characteristics, see benchmarks.txt
|
32
|
+
b = GoogleHashDenseIntToRuby.new # :int => Ruby -- keys are stored as "native" ints, values are ruby objects
|
33
33
|
c = GoogleHashSparseIntToInt.new # :int => :int
|
34
|
-
|
34
|
+
|
35
|
+
Here's the full list of availables:
|
36
|
+
|
37
|
+
>> Object.constants.each{|k k if k =~ /google/i }
|
38
|
+
|
39
|
+
GoogleHashDenseLongToLong
|
40
|
+
GoogleHashSparseLongToLong
|
41
|
+
GoogleHashDenseLongToInt
|
42
|
+
GoogleHashSparseLongToInt
|
43
|
+
GoogleHashDenseLongToRuby
|
44
|
+
GoogleHashSparseLongToRuby
|
45
|
+
GoogleHashDenseDoubleToLong
|
46
|
+
GoogleHashSparseDoubleToLong
|
47
|
+
GoogleHashDenseDoubleToInt
|
48
|
+
GoogleHashSparseDoubleToInt
|
49
|
+
GoogleHashDenseDoubleToRuby
|
50
|
+
GoogleHashSparseDoubleToRuby
|
51
|
+
GoogleHashDenseIntToLong
|
52
|
+
GoogleHashSparseIntToLong
|
53
|
+
GoogleHashDenseIntToInt
|
54
|
+
GoogleHashSparseIntToInt
|
55
|
+
GoogleHashDenseIntToRuby
|
56
|
+
GoogleHashSparseIntToRuby
|
57
|
+
GoogleHashDenseRubyToLong
|
58
|
+
GoogleHashSparseRubyToLong
|
59
|
+
GoogleHashDenseRubyToInt
|
60
|
+
GoogleHashSparseRubyToInt
|
61
|
+
GoogleHashDenseRubyToRuby
|
62
|
+
GoogleHashSparseRubyToRuby
|
63
|
+
|
64
|
+
(long is "better" than int on 64 bit systems only)
|
65
|
+
|
66
|
+
and how to use them:
|
35
67
|
|
36
68
|
a[3] = 4
|
37
69
|
b[4] = 'abc'
|
38
70
|
b['abc'] = 'some complex object'
|
39
71
|
c[3] = 4 # all you can use are ints...
|
40
72
|
|
41
|
-
|
42
|
-
|
43
|
-
a.keys
|
44
|
-
=> Array
|
45
|
-
a.values
|
46
|
-
=> Array
|
47
|
-
|
48
|
-
For a complete list, see types.txt, but it's all the various combinations of Ruby, Int, and Long.
|
73
|
+
Use them like "normal" hashes with the same method names.
|
49
74
|
|
50
|
-
To learn if sparse or dense is right for you, check
|
75
|
+
To learn if sparse or dense is right for you, check the documentation:
|
51
76
|
|
52
77
|
http://google-sparsehash.googlecode.com/svn/trunk/doc/index.html
|
53
78
|
Dense is faster, sparse uses less memory.
|
@@ -64,7 +89,7 @@ ex: currently it uses longs internally instead of ints--if you want ints or char
|
|
64
89
|
|
65
90
|
if you want it to remember insertion order, I could do that, too, or native "store away" strings/bignums, whatever.
|
66
91
|
|
67
|
-
Could also add vectors, vector(pairs), priority queues, floats, native bignums, other more complex types, if anybody
|
92
|
+
Could also add vectors, vector(pairs), priority queues, floats, native bignums, other more complex types, if anybody wants me to.
|
68
93
|
|
69
94
|
This is meant to be one more tool in the rubyists toolbelt when trying to optimize speed-wise, and plans to expand to more types, but at least with this release it has a #each method.
|
70
95
|
|
@@ -80,4 +105,4 @@ Related:
|
|
80
105
|
|
81
106
|
judy http://groups.google.com/group/ruby-talk-google/browse_thread/thread/05ed587925526a7f/314375891d12b672?lnk=raot
|
82
107
|
|
83
|
-
NArray gem : provides "native" type arrays (and X-
|
108
|
+
NArray gem : provides "native" type arrays (and X-Dimensional arrays--all in native memory, so also saves memory as this gem does)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/ext/extconf.rb
CHANGED
@@ -38,26 +38,35 @@ ruby_key = {:convert_keys_from_ruby => "", :convert_keys_to_ruby => "", :key_ty
|
|
38
38
|
:extra_hash_params => ", hashrb, eqrb", :unreachable_key => "current_instance"} # TODO NULL is false here?
|
39
39
|
int_key = {:assert_key_type => 'T_FIXNUM', :convert_keys_from_ruby => "FIX2INT",
|
40
40
|
:convert_keys_to_ruby => "INT2FIX", :key_type => "int", :unreachable_key => "1<<#{unreachable_int}"}
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
# "long" is useful on 64 bit...
|
43
|
+
long_key = {:assert_key_type => 'T_FIXNUM', :convert_keys_from_ruby => "FIX2LONG",
|
44
|
+
:convert_keys_to_ruby => "LONG2FIX", :key_type => "long", :unreachable_key => "1<<#{unreachable_int}"}
|
45
|
+
|
46
|
+
|
47
|
+
bignum_as_double_key = {:assert_key_type => ['T_BIGNUM', 'T_FIXNUM'], :convert_keys_from_ruby => "rb_big2dbl",
|
43
48
|
:convert_keys_to_ruby => "rb_dbl2big", :key_type => "double", :unreachable_key => "1<<#{unreachable_int}", # LODO is this a bignum value though?
|
44
49
|
:extra_hash_params => ", hashdouble, eqdouble",
|
45
|
-
:extra_set_code => "if(TYPE(set_this) == T_FIXNUM)\nset_this = rb_int2big(set_this);",
|
46
|
-
:extra_get_code => "if(TYPE(get_this) == T_FIXNUM) \n get_this = rb_int2big(get_this);"
|
47
|
-
}
|
48
|
-
|
50
|
+
:extra_set_code => "if(TYPE(set_this) == T_FIXNUM)\nset_this = rb_int2big(FIX2INT(set_this));",
|
51
|
+
:extra_get_code => "if(TYPE(get_this) == T_FIXNUM) \n get_this = rb_int2big(FIX2INT(get_this));"
|
52
|
+
}
|
49
53
|
|
50
54
|
ruby_value = {:value_type => "VALUE", :english_value_type => "ruby"}
|
51
55
|
int_value = {:assert_value_type => 'T_FIXNUM', :convert_values_from_ruby => "FIX2INT",
|
52
56
|
:convert_values_to_ruby => "INT2FIX", :value_type => "int"}
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
+
long_value = {:assert_value_type => 'T_FIXNUM', :convert_values_from_ruby => "FIX2LONG",
|
58
|
+
:convert_values_to_ruby => "LONG2FIX", :value_type => "long"}
|
59
|
+
|
60
|
+
bignum_as_double_value = {:assert_value_type => ['T_BIGNUM', 'T_FIXNUM'], :convert_values_from_ruby => "rb_big2dbl",
|
61
|
+
:convert_values_to_ruby => "rb_dbl2big", :value_type => "double",
|
62
|
+
:extra_set_code2 => "if(TYPE(to_this) == T_FIXNUM)\nto_this = rb_int2big(FIX2INT(to_this));"
|
63
|
+
}
|
64
|
+
|
65
|
+
|
57
66
|
init_funcs = []
|
58
67
|
|
59
|
-
for key in [ruby_key, int_key,
|
60
|
-
for value in [ruby_value, int_value] do
|
68
|
+
for key in [ruby_key, int_key, bignum_as_double_key, long_key] do
|
69
|
+
for value in [ruby_value, int_value, long_value, bignum_as_double_value] do
|
61
70
|
options = key.merge(value)
|
62
71
|
for type in ['sparse', 'dense'] do
|
63
72
|
|
@@ -75,7 +84,8 @@ for key in [ruby_key, int_key, bignum_key] do
|
|
75
84
|
assert_key_type2 = [options[:assert_key_type]].flatten[1]
|
76
85
|
convert_values_from_ruby = options[:convert_values_from_ruby]
|
77
86
|
convert_values_to_ruby = options[:convert_values_to_ruby]
|
78
|
-
assert_value_type = options[:assert_value_type]
|
87
|
+
assert_value_type = [options[:assert_value_type]].flatten[0]
|
88
|
+
assert_value_type2 = [options[:assert_value_type]].flatten[1]
|
79
89
|
|
80
90
|
extra_hash_params = options[:extra_hash_params]
|
81
91
|
|
data/ext/temp/extconf.rb
ADDED
@@ -73,9 +73,8 @@ struct hashdouble {
|
|
73
73
|
<% end %>
|
74
74
|
|
75
75
|
<% if key_type == 'VALUE' %>
|
76
|
-
static hash<const char*> H;
|
77
|
-
|
78
|
-
// hashing it is like hash<const char*>
|
76
|
+
// static hash<const char*> H; // unused currently...
|
77
|
+
// using it is like hash<const char*>
|
79
78
|
|
80
79
|
struct eqrb
|
81
80
|
{
|
@@ -213,18 +212,21 @@ static VALUE rb_ghash_set(VALUE cb, VALUE set_this, VALUE to_this) {
|
|
213
212
|
|
214
213
|
<% if assert_value_type %>
|
215
214
|
if(!(TYPE(to_this) == <%= assert_value_type %>)) {
|
215
|
+
<%= "if(!(TYPE(to_this) == #{assert_value_type2}))" if assert_value_type2 %>
|
216
216
|
rb_raise(rb_eTypeError, "not valid value <%=assert_value_type%>");
|
217
217
|
}
|
218
218
|
<% end %>
|
219
219
|
|
220
220
|
<%= options[:extra_set_code] %>
|
221
221
|
|
222
|
+
<%= options[:extra_set_code2] %>
|
223
|
+
|
222
224
|
RCallback* cbs = GetCallbackStruct(cb);
|
223
225
|
(*cbs->hash_map)[ <%= convert_keys_from_ruby %>(set_this)] = <%= convert_values_from_ruby %>(to_this);
|
224
226
|
return to_this; // ltodo test that it returns value...
|
225
227
|
}
|
226
228
|
|
227
|
-
static VALUE rb_ghash_get(VALUE cb, VALUE get_this) {
|
229
|
+
static VALUE rb_ghash_get(VALUE cb, VALUE get_this, int just_check_for_presence) {
|
228
230
|
// TODO optionally not type check assert anywhere [?]
|
229
231
|
<% if assert_key_type %>
|
230
232
|
if(!(TYPE(get_this) == <%= assert_key_type %>)) {
|
@@ -237,12 +239,33 @@ static VALUE rb_ghash_get(VALUE cb, VALUE get_this) {
|
|
237
239
|
|
238
240
|
<%= type %>_hash_map< <%= key_type %>, <%= value_type %> <%= extra_hash_params %> >::iterator out = cbs->hash_map->find(<%= convert_keys_from_ruby %>(get_this));
|
239
241
|
|
240
|
-
if(out == cbs->hash_map->end()) { // not found...hmm...is this False, though?
|
241
|
-
|
242
|
-
|
243
|
-
|
242
|
+
if(out == cbs->hash_map->end()) { // not found...hmm...is this False, though?
|
243
|
+
if(just_check_for_presence)
|
244
|
+
return Qfalse;
|
245
|
+
else
|
246
|
+
return Qnil;
|
247
|
+
} else {
|
248
|
+
if(just_check_for_presence)
|
249
|
+
return Qtrue;
|
250
|
+
else
|
251
|
+
return <%= convert_values_to_ruby %>(out->second);
|
244
252
|
}
|
253
|
+
|
245
254
|
}
|
255
|
+
|
256
|
+
static VALUE rb_ghash_get_value(VALUE cb, VALUE get_this) {
|
257
|
+
return rb_ghash_get(cb, get_this, 0);
|
258
|
+
}
|
259
|
+
|
260
|
+
static VALUE rb_ghash_get_present(VALUE cb, VALUE get_this) {
|
261
|
+
return rb_ghash_get(cb, get_this, 1);
|
262
|
+
}
|
263
|
+
|
264
|
+
static VALUE rb_ghash_size(VALUE cb) {
|
265
|
+
RCallback* incoming = GetCallbackStruct(cb);
|
266
|
+
return INT2FIX(incoming->hash_map->size());
|
267
|
+
}
|
268
|
+
|
246
269
|
|
247
270
|
static VALUE rb_ghash_each(VALUE cb) {
|
248
271
|
RCallback* incoming = GetCallbackStruct(cb);
|
@@ -299,11 +322,16 @@ void init_<%= type %>_<%= english_key_type %>_to_<%= english_value_type %>() {
|
|
299
322
|
|
300
323
|
rb_define_method(rb_cGoogleHashLocal, "initialize", RUBY_METHOD_FUNC(rb_mri_hash_new), 0);
|
301
324
|
rb_define_method(rb_cGoogleHashLocal, "[]=", RUBY_METHOD_FUNC(rb_ghash_set), 2);
|
302
|
-
rb_define_method(rb_cGoogleHashLocal, "[]", RUBY_METHOD_FUNC(
|
325
|
+
rb_define_method(rb_cGoogleHashLocal, "[]", RUBY_METHOD_FUNC(rb_ghash_get_value), 1);
|
303
326
|
rb_define_method(rb_cGoogleHashLocal, "each", RUBY_METHOD_FUNC(rb_ghash_each), 0);
|
304
327
|
rb_define_method(rb_cGoogleHashLocal, "values", RUBY_METHOD_FUNC(rb_ghash_values), 0);
|
305
328
|
rb_define_method(rb_cGoogleHashLocal, "keys", RUBY_METHOD_FUNC(rb_ghash_keys), 0);
|
329
|
+
rb_define_method(rb_cGoogleHashLocal, "has_key?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
330
|
+
rb_define_method(rb_cGoogleHashLocal, "key?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
331
|
+
rb_define_method(rb_cGoogleHashLocal, "member?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
332
|
+
rb_define_method(rb_cGoogleHashLocal, "include?", RUBY_METHOD_FUNC(rb_ghash_get_present), 1);
|
306
333
|
rb_define_method(rb_cGoogleHashLocal, "keys_combination_2", RUBY_METHOD_FUNC(rb_ghash_combination_2), 0);
|
334
|
+
rb_define_method(rb_cGoogleHashLocal, "length", RUBY_METHOD_FUNC(rb_ghash_size), 0);
|
307
335
|
id_eql = rb_intern("eql?");
|
308
336
|
id_hash = rb_intern("hash");
|
309
337
|
}
|
data/spec/spec.google_hash.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require 'rubygems'
|
1
|
+
require 'rubygems'
|
2
2
|
require 'sane'
|
3
|
-
require_relative '../ext/google_hash
|
3
|
+
require_relative '../ext/google_hash'
|
4
4
|
begin
|
5
5
|
require 'spec/autorun'
|
6
6
|
rescue LoadError
|
@@ -13,8 +13,8 @@ describe "google_hash" do
|
|
13
13
|
@subject = GoogleHashSparseIntToRuby.new
|
14
14
|
end
|
15
15
|
|
16
|
-
it "should be instantiable" do
|
17
|
-
|
16
|
+
it "should be instantiable [new method should not raise]" do
|
17
|
+
GoogleHashSparseIntToRuby.new
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should allow you to set a key" do
|
@@ -36,23 +36,38 @@ describe "google_hash" do
|
|
36
36
|
assert all_got.sort == ['abc', 'def']
|
37
37
|
end
|
38
38
|
|
39
|
+
it "should have key methods" do
|
40
|
+
@subject = a = GoogleHashDenseDoubleToInt.new
|
41
|
+
@subject[33] = 3
|
42
|
+
for method in [:has_key?, :include?, :key?, :member?] do
|
43
|
+
@subject.send(method, 33).should == true
|
44
|
+
@subject.send(method, 34).should == false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
39
49
|
it "should have all the methods desired" do
|
40
|
-
pending "need"
|
41
50
|
# guess these could all be tests, themselves...
|
42
|
-
@subject.each_key {}
|
43
|
-
@subject.each_value{}
|
44
51
|
@subject.each{}
|
45
52
|
@subject[33] = 'abc'
|
46
53
|
@subject.length.should == 1
|
54
|
+
@subject.each{}
|
55
|
+
@subject.each{|k, v|
|
56
|
+
k.should == 33
|
57
|
+
v.should == 'abc'
|
58
|
+
}
|
47
59
|
@subject.delete(33).should == 'abc'
|
60
|
+
@subject.length.should == 0
|
61
|
+
@subject[33] = 'abc'
|
62
|
+
@subject.length.should == 1
|
48
63
|
@subject.clear
|
49
64
|
@subject.length.should == 0
|
50
65
|
end
|
51
|
-
|
52
|
-
it "should not leak" do
|
53
|
-
pending "testing if it leaks"
|
54
|
-
end
|
55
66
|
|
67
|
+
it 'should not be able to set the absent key for double' do
|
68
|
+
fail
|
69
|
+
end
|
70
|
+
|
56
71
|
def populate(a)
|
57
72
|
a['abc'] = 'def'
|
58
73
|
a['bbc'] = 'yoyo'
|
@@ -109,8 +124,8 @@ describe "google_hash" do
|
|
109
124
|
pending "if necessary"
|
110
125
|
end
|
111
126
|
|
112
|
-
it "should do longs
|
113
|
-
|
127
|
+
it "should do longs" do
|
128
|
+
GoogleHashDenseLongToLong.new
|
114
129
|
end
|
115
130
|
|
116
131
|
it "should do 63 bit thingy for longs on 64 bit" do
|
@@ -169,6 +184,7 @@ describe "google_hash" do
|
|
169
184
|
end
|
170
185
|
|
171
186
|
it "should not leak" do
|
187
|
+
pending 'something that might leak'
|
172
188
|
a = GoogleHashDenseIntToInt.new
|
173
189
|
100_000.times {
|
174
190
|
a[1] = 1
|
@@ -186,25 +202,27 @@ describe "google_hash" do
|
|
186
202
|
end
|
187
203
|
|
188
204
|
it "should do float values as doubles" do
|
205
|
+
pending "interest in floats"
|
189
206
|
a = GoogleHashDenseDoubleToInt.new
|
190
207
|
a[1.0] = 1
|
191
208
|
a[1.0].should == 1
|
192
209
|
end
|
193
210
|
|
194
211
|
it "should do bignum to doubles et al" do
|
195
|
-
pending
|
196
212
|
a = GoogleHashDenseDoubleToDouble.new
|
197
213
|
a[10000000000000000000] = 1
|
198
214
|
a[10000000000000000000].should == 1
|
199
215
|
a[1] = 10000000000000000000
|
200
216
|
a[1].should == 10000000000000000000
|
217
|
+
a[4] = 3
|
218
|
+
a[4].should == 3
|
201
219
|
a[10000000000000000000] = 10000000000000000000
|
202
220
|
a[10000000000000000000].should == 10000000000000000000
|
203
221
|
end
|
204
222
|
|
205
|
-
it "should
|
223
|
+
it "should allow for storing true bignums" do
|
206
224
|
pending
|
207
|
-
fail 'same as above plus'
|
225
|
+
fail 'same as above plus the following:'
|
208
226
|
a = GoogleHashDenseBignumToRuby.new
|
209
227
|
a[10000000000000000000] = 'abc'
|
210
228
|
end
|
@@ -223,7 +241,12 @@ describe "google_hash" do
|
|
223
241
|
|
224
242
|
it "should have an Enumerator for values, keys, an on demand, getNext enumerator object..."
|
225
243
|
|
226
|
-
it "should have a block access for values, keys"
|
244
|
+
it "should have a block access for values, keys" do
|
245
|
+
pending "interest"
|
246
|
+
@a[3] = 4
|
247
|
+
a.each_value {}
|
248
|
+
a.each_key {}
|
249
|
+
end
|
227
250
|
|
228
251
|
it "should have sets, too, not just hashes"
|
229
252
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- rogerdpack
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-27 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -36,6 +36,7 @@ executables: []
|
|
36
36
|
|
37
37
|
extensions:
|
38
38
|
- ext/extconf.rb
|
39
|
+
- ext/temp/extconf.rb
|
39
40
|
extra_rdoc_files:
|
40
41
|
- README
|
41
42
|
files:
|
@@ -128,6 +129,7 @@ files:
|
|
128
129
|
- spec/scale.rb
|
129
130
|
- spec/spec.google_hash.rb
|
130
131
|
- types.txt
|
132
|
+
- ext/temp/extconf.rb
|
131
133
|
has_rdoc: true
|
132
134
|
homepage: http://github.com/rdp/ruby_google_hash
|
133
135
|
licenses: []
|