sparse_array 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/ext/sp_ar.c +52 -55
  2. data/lib/sparse_array/version.rb +1 -1
  3. metadata +10 -4
data/ext/sp_ar.c CHANGED
@@ -6,19 +6,9 @@
6
6
  #endif
7
7
  #include <string.h>
8
8
 
9
- #if SIZEOF_LONG == SIZEOF_VOIDP
10
- typedef unsigned long st_data_t;
11
- #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
12
- typedef unsigned LONG_LONG st_data_t;
13
- #else
14
- # error ---->> sp_ar.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
15
- #endif
16
-
17
9
  typedef unsigned int spar_index_t;
18
- #define spar_STOP ST_STOP
19
- #define spar_CONTINUE ST_CONTINUE
20
10
 
21
- #define spar_EMPTY 0
11
+ #define SPAR_EMPTY 0
22
12
 
23
13
  typedef struct spar_entry {
24
14
  spar_index_t next;
@@ -33,7 +23,7 @@ typedef struct spar_table {
33
23
  spar_entry *entries;
34
24
  } spar_table;
35
25
 
36
- #define spar_EMPTY_TABLE {0, 0, 0, 0};
26
+ #define SPAR_EMPTY_TABLE {0, 0, 0, 0};
37
27
  static void spar_init_table(spar_table *, spar_index_t);
38
28
  static spar_table *spar_new_table();
39
29
  static int spar_insert(spar_table *, spar_index_t, st_data_t);
@@ -43,14 +33,13 @@ static void spar_clear(spar_table *);
43
33
  static void spar_free_table(spar_table *);
44
34
  static size_t spar_memsize(const spar_table *);
45
35
  static void spar_copy_to(spar_table*, spar_table*);
46
- typedef int (*spar_iter_func)(spar_index_t key, st_data_t val, st_data_t arg);
47
36
 
48
37
  #define SPAR_FOREACH_START_I(table, entry) do { \
49
38
  spar_table *T##entry = (table); \
50
39
  spar_index_t K##entry; \
51
40
  for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \
52
41
  spar_entry *entry = T##entry->entries + K##entry; \
53
- if (entry->next != spar_EMPTY) { \
42
+ if (entry->next != SPAR_EMPTY) { \
54
43
  st_data_t value = entry->value
55
44
  #define SPAR_FOREACH_END() } } } while(0)
56
45
 
@@ -67,10 +56,10 @@ typedef int (*spar_iter_func)(spar_index_t key, st_data_t val, st_data_t arg);
67
56
  #define spar_entry_alloc(n) (spar_entry*)calloc((n), sizeof(spar_entry))
68
57
  #define spar_entry_dealloc(entries) free(entries)
69
58
 
70
- #define spar_LAST 1
71
- #define spar_OFFSET 2
59
+ #define SPAR_LAST 1
60
+ #define SPAR_OFFSET 2
72
61
 
73
- #define spar_MIN_SIZE 4
62
+ #define SPAR_MIN_SIZE 4
74
63
 
75
64
  static void
76
65
  spar_init_table(register spar_table *table, spar_index_t num_bins)
@@ -97,33 +86,36 @@ spar_new_table()
97
86
  static inline spar_index_t
98
87
  calc_pos(register spar_table* table, spar_index_t key)
99
88
  {
100
- /* this formula is empirical */
101
- /* it has no good avalance, but works well in our case */
102
- key ^= key >> 16;
103
- key *= 0x445229;
104
- return (key + (key >> 16)) % table->num_bins;
89
+ uint64_t res = (uint64_t)key * 0x85ebca6bull;
90
+ return ((spar_index_t)res ^ (spar_index_t)(res >> 32)) % table->num_bins;
105
91
  }
106
92
 
107
93
  static void
108
94
  fix_empty(register spar_table* table)
109
95
  {
110
96
  while(--table->free_pos &&
111
- table->entries[table->free_pos-1].next != spar_EMPTY);
97
+ table->entries[table->free_pos-1].next != SPAR_EMPTY);
112
98
  }
113
99
 
114
100
  #define FLOOR_TO_4 ((~((spar_index_t)0)) << 2)
101
+ static int checks[][3] = {
102
+ { 1, 2, 3 },
103
+ { 2, 3, 0 },
104
+ { 3, 1, 0 },
105
+ { 2, 1, 0 },
106
+ };
115
107
  static spar_index_t
116
108
  find_empty(register spar_table* table, register spar_index_t pos)
117
109
  {
118
110
  spar_index_t new_pos = table->free_pos-1;
119
111
  spar_entry *entry;
112
+ int *check = checks[pos&3];
120
113
  pos &= FLOOR_TO_4;
121
114
  entry = table->entries+pos;
122
115
 
123
- if (entry->next == spar_EMPTY) { new_pos = pos; }
124
- else if ((++entry)->next == spar_EMPTY) { new_pos = pos + 1; }
125
- else if ((++entry)->next == spar_EMPTY) { new_pos = pos + 2; }
126
- else if ((++entry)->next == spar_EMPTY) { new_pos = pos + 3; }
116
+ if (entry[check[0]].next == SPAR_EMPTY) { new_pos = pos + check[0];}
117
+ else if (entry[check[1]].next == SPAR_EMPTY) { new_pos = pos + check[1];}
118
+ else if (entry[check[2]].next == SPAR_EMPTY) { new_pos = pos + check[2];}
127
119
 
128
120
  if (new_pos+1 == table->free_pos) fix_empty(table);
129
121
  return new_pos;
@@ -140,14 +132,14 @@ spar_insert(register spar_table* table, register spar_index_t key, st_data_t val
140
132
  register spar_entry *entry;
141
133
 
142
134
  if (table->num_bins == 0) {
143
- spar_init_table(table, spar_MIN_SIZE);
135
+ spar_init_table(table, SPAR_MIN_SIZE);
144
136
  }
145
137
 
146
138
  pos = calc_pos(table, key);
147
139
  entry = table->entries + pos;
148
140
 
149
- if (entry->next == spar_EMPTY) {
150
- entry->next = spar_LAST;
141
+ if (entry->next == SPAR_EMPTY) {
142
+ entry->next = SPAR_LAST;
151
143
  entry->key = key;
152
144
  entry->value = value;
153
145
  table->num_entries++;
@@ -184,8 +176,8 @@ insert_into_chain(register spar_table* table, register spar_index_t key, st_data
184
176
  spar_entry *entry = table->entries + pos, *new_entry;
185
177
  spar_index_t new_pos;
186
178
 
187
- while (entry->next != spar_LAST) {
188
- pos = entry->next - spar_OFFSET;
179
+ while (entry->next != SPAR_LAST) {
180
+ pos = entry->next - SPAR_OFFSET;
189
181
  entry = table->entries + pos;
190
182
  if (entry->key == key) {
191
183
  entry->value = value;
@@ -200,9 +192,9 @@ insert_into_chain(register spar_table* table, register spar_index_t key, st_data
200
192
 
201
193
  new_pos = find_empty(table, pos);
202
194
  new_entry = table->entries + new_pos;
203
- entry->next = new_pos + spar_OFFSET;
195
+ entry->next = new_pos + SPAR_OFFSET;
204
196
 
205
- new_entry->next = spar_LAST;
197
+ new_entry->next = SPAR_LAST;
206
198
  new_entry->key = key;
207
199
  new_entry->value = value;
208
200
  table->num_entries++;
@@ -219,12 +211,12 @@ insert_into_main(register spar_table* table, spar_index_t key, st_data_t value,
219
211
 
220
212
  *new_entry = *entry;
221
213
 
222
- while((npos = table->entries[prev_pos].next - spar_OFFSET) != pos) {
214
+ while((npos = table->entries[prev_pos].next - SPAR_OFFSET) != pos) {
223
215
  prev_pos = npos;
224
216
  }
225
- table->entries[prev_pos].next = new_pos + spar_OFFSET;
217
+ table->entries[prev_pos].next = new_pos + SPAR_OFFSET;
226
218
 
227
- entry->next = spar_LAST;
219
+ entry->next = SPAR_LAST;
228
220
  entry->key = key;
229
221
  entry->value = value;
230
222
  table->num_entries++;
@@ -235,13 +227,12 @@ static spar_index_t
235
227
  new_size(spar_index_t num_entries)
236
228
  {
237
229
  spar_index_t msb = num_entries;
238
- msb |= msb >> 1;
239
230
  msb |= msb >> 2;
240
231
  msb |= msb >> 4;
241
232
  msb |= msb >> 8;
242
233
  msb |= msb >> 16;
243
- msb = ((msb >> 4) + 1) << 3;
244
- return (num_entries & (msb | (msb >> 1))) + (msb >> 1);
234
+ msb |= msb >> 3;
235
+ return ((msb >> 3) + 1) << 4;
245
236
  }
246
237
 
247
238
  static void
@@ -261,7 +252,7 @@ resize(register spar_table *table)
261
252
  entry = table->entries;
262
253
 
263
254
  for(i = 0; i < table->num_bins; i++, entry++) {
264
- if (entry->next != spar_EMPTY) {
255
+ if (entry->next != SPAR_EMPTY) {
265
256
  spar_insert(&tmp_table, entry->key, entry->value);
266
257
  }
267
258
  }
@@ -270,23 +261,29 @@ resize(register spar_table *table)
270
261
  }
271
262
 
272
263
  static int
273
- spar_lookup(register spar_table *table, register spar_index_t key, st_data_t *value)
264
+ spar_lookup(spar_table *table, register spar_index_t key, st_data_t *value)
274
265
  {
275
266
  register spar_entry *entry;
267
+ register spar_index_t next;
268
+ register spar_entry *entries = table->entries;
276
269
 
277
270
  if (table->num_entries == 0) return 0;
278
271
 
279
- entry = table->entries + calc_pos(table, key);
280
- if (entry->next == spar_EMPTY) return 0;
281
-
272
+ entry = entries + calc_pos(table, key);
273
+ next = entry->next;
274
+ if (next == SPAR_EMPTY) return 0;
282
275
  if (entry->key == key) goto found;
283
- if (entry->next == spar_LAST) return 0;
276
+ if (next == SPAR_LAST) return 0;
277
+
278
+ entries -= SPAR_OFFSET;
284
279
 
285
- entry = table->entries + (entry->next - spar_OFFSET);
280
+ entry = entries + next;
281
+ next = entry->next;
286
282
  if (entry->key == key) goto found;
287
283
 
288
- while(entry->next != spar_LAST) {
289
- entry = table->entries + (entry->next - spar_OFFSET);
284
+ while(next != SPAR_LAST) {
285
+ entry = entries + next;
286
+ next = entry->next;
290
287
  if (entry->key == key) goto found;
291
288
  }
292
289
  return 0;
@@ -320,20 +317,20 @@ spar_delete(spar_table *table, spar_index_t key, st_data_t *value)
320
317
  pos = calc_pos(table, key);
321
318
  entry = table->entries + pos;
322
319
 
323
- if (entry->next == spar_EMPTY) goto not_found;
320
+ if (entry->next == SPAR_EMPTY) goto not_found;
324
321
 
325
322
  do {
326
323
  if (entry->key == key) {
327
324
  if (value) *value = entry->value;
328
- if (entry->next != spar_LAST) {
329
- spar_index_t npos = entry->next - spar_OFFSET;
325
+ if (entry->next != SPAR_LAST) {
326
+ spar_index_t npos = entry->next - SPAR_OFFSET;
330
327
  *entry = table->entries[npos];
331
328
  memset(table->entries + npos, 0, sizeof(spar_entry));
332
329
  }
333
330
  else {
334
331
  memset(table->entries + pos, 0, sizeof(spar_entry));
335
332
  if (~prev_pos) {
336
- table->entries[prev_pos].next = spar_LAST;
333
+ table->entries[prev_pos].next = SPAR_LAST;
337
334
  }
338
335
  }
339
336
  table->num_entries--;
@@ -342,9 +339,9 @@ spar_delete(spar_table *table, spar_index_t key, st_data_t *value)
342
339
  }
343
340
  return 1;
344
341
  }
345
- if (entry->next == spar_LAST) break;
342
+ if (entry->next == SPAR_LAST) break;
346
343
  prev_pos = pos;
347
- pos = entry->next - spar_OFFSET;
344
+ pos = entry->next - SPAR_OFFSET;
348
345
  entry = table->entries + pos;
349
346
  } while(1);
350
347
 
@@ -1,3 +1,3 @@
1
1
  class SparseArray
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparse_array
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-19 00:00:00.000000000 Z
12
+ date: 2013-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- type: :development
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
17
  - - ~>
@@ -27,8 +26,8 @@ dependencies:
27
26
  none: false
28
27
  prerelease: false
29
28
  name: bundler
30
- - !ruby/object:Gem::Dependency
31
29
  type: :development
30
+ - !ruby/object:Gem::Dependency
32
31
  requirement: !ruby/object:Gem::Requirement
33
32
  requirements:
34
33
  - - ! '>='
@@ -43,6 +42,7 @@ dependencies:
43
42
  none: false
44
43
  prerelease: false
45
44
  name: rake
45
+ type: :development
46
46
  description: Sparse Array - map from integers (0..2**32-1) to objects
47
47
  email:
48
48
  - funny.falcon@gmail.com
@@ -69,13 +69,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
69
  requirements:
70
70
  - - ! '>='
71
71
  - !ruby/object:Gem::Version
72
+ hash: -4038731035297289892
72
73
  version: '0'
74
+ segments:
75
+ - 0
73
76
  none: false
74
77
  required_rubygems_version: !ruby/object:Gem::Requirement
75
78
  requirements:
76
79
  - - ! '>='
77
80
  - !ruby/object:Gem::Version
81
+ hash: -4038731035297289892
78
82
  version: '0'
83
+ segments:
84
+ - 0
79
85
  none: false
80
86
  requirements: []
81
87
  rubyforge_project: