sparse_array 0.0.1 → 0.0.3

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.
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: