google_hash 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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
- d = GoogleHashSparseIntToInt.new # :long => :long (longs are 8 byte ints on 64-bit machines, so can store larger numbers)
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
- a.each{|k, v| ... }
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 their documentation:
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 asks me to.
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-D array)
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.5.1
1
+ 0.6.0
@@ -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
- # "long" is not useful to us since it's the same as int...
42
- bignum_key = {:assert_key_type => ['T_BIGNUM', 'T_FIXNUM'], :convert_keys_from_ruby => "rb_big2dbl",
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
- } # fixnum's can never be zero...
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
- #bignum_value = {:assert_value_type => 'T_BIGNUM', :convert_values_from_ruby => "rb_big2dbl",
55
- #:convert_values_to_ruby => "rb_dbl2big", :value_type => "double", }
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, bignum_key] do
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
 
@@ -0,0 +1,11 @@
1
+ # Loads mkmf which is used to make makefiles for Ruby extensions
2
+ require 'mkmf'
3
+
4
+ # Give it a name
5
+ extension_name = 'mytest'
6
+
7
+ # The destination
8
+ dir_config(extension_name)
9
+
10
+ # Do the work
11
+ create_makefile(extension_name)
@@ -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
- return Qnil;
242
- } else {
243
- return <%= convert_values_to_ruby %>(out->second);
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(rb_ghash_get), 1);
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
  }
@@ -1,6 +1,6 @@
1
- require 'rubygems' if RUBY_VERSION < '1.9'
1
+ require 'rubygems'
2
2
  require 'sane'
3
- require_relative '../ext/google_hash.so'
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
- # nothing
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 eventually" do
113
- pending "caring about 64 bit"
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 have really real bignums" do
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
- - 5
8
- - 1
9
- version: 0.5.1
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-22 00:00:00 -06:00
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: []