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