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.
- data/ext/sp_ar.c +52 -55
- data/lib/sparse_array/version.rb +1 -1
- 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
|
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
|
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 !=
|
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
|
71
|
-
#define
|
59
|
+
#define SPAR_LAST 1
|
60
|
+
#define SPAR_OFFSET 2
|
72
61
|
|
73
|
-
#define
|
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
|
-
|
101
|
-
|
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 !=
|
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
|
124
|
-
else if (
|
125
|
-
else if (
|
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,
|
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 ==
|
150
|
-
entry->next =
|
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 !=
|
188
|
-
pos = entry->next -
|
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 +
|
195
|
+
entry->next = new_pos + SPAR_OFFSET;
|
204
196
|
|
205
|
-
new_entry->next =
|
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 -
|
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 +
|
217
|
+
table->entries[prev_pos].next = new_pos + SPAR_OFFSET;
|
226
218
|
|
227
|
-
entry->next =
|
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
|
244
|
-
return (
|
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 !=
|
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(
|
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 =
|
280
|
-
|
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 (
|
276
|
+
if (next == SPAR_LAST) return 0;
|
277
|
+
|
278
|
+
entries -= SPAR_OFFSET;
|
284
279
|
|
285
|
-
entry =
|
280
|
+
entry = entries + next;
|
281
|
+
next = entry->next;
|
286
282
|
if (entry->key == key) goto found;
|
287
283
|
|
288
|
-
while(
|
289
|
-
entry =
|
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 ==
|
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 !=
|
329
|
-
spar_index_t npos = entry->next -
|
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 =
|
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 ==
|
342
|
+
if (entry->next == SPAR_LAST) break;
|
346
343
|
prev_pos = pos;
|
347
|
-
pos = entry->next -
|
344
|
+
pos = entry->next - SPAR_OFFSET;
|
348
345
|
entry = table->entries + pos;
|
349
346
|
} while(1);
|
350
347
|
|
data/lib/sparse_array/version.rb
CHANGED
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.
|
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-
|
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:
|