rejuicer 0.0.3 → 0.0.4
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/Manifest.txt +7 -2
- data/README.rdoc +7 -0
- data/ext/extconf.rb +1 -1
- data/ext/rejuicer_set/and.c +97 -0
- data/ext/rejuicer_set/index.c +119 -0
- data/ext/rejuicer_set/init.c +183 -0
- data/ext/rejuicer_set/main.c +213 -0
- data/ext/rejuicer_set/or.c +109 -0
- data/ext/{rejuicer_set.h → rejuicer_set/rejuicer_set.h} +24 -1
- data/ext/rejuicer_set/util.c +79 -0
- data/lib/rejuicer.rb +36 -7
- metadata +10 -5
- data/ext/rejuicer_set.c +0 -468
@@ -0,0 +1,109 @@
|
|
1
|
+
//************************************
|
2
|
+
// rejuicer.c
|
3
|
+
//
|
4
|
+
// Tsukasa OISHI
|
5
|
+
//
|
6
|
+
// 2010/03/17
|
7
|
+
//************************************
|
8
|
+
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <ruby.h>
|
13
|
+
#include "rejuicer_set.h"
|
14
|
+
|
15
|
+
//
|
16
|
+
// join
|
17
|
+
//
|
18
|
+
void join(root_node ret_set, root_node set0, root_node set1)
|
19
|
+
{
|
20
|
+
int i;
|
21
|
+
|
22
|
+
if (set0->size == 0 && set1->size == 0) {
|
23
|
+
return;
|
24
|
+
} else if (set0->size == 0) {
|
25
|
+
copy_root_node(ret_set, set1);
|
26
|
+
return;
|
27
|
+
} else if (set1->size == 0) {
|
28
|
+
copy_root_node(ret_set, set0);
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
for (i = 0; i < ROOT_NODE_SIZE; i++) {
|
33
|
+
if (set0->index[i] && set1->index[i]) {
|
34
|
+
ret_set->index[i] = (branch_node)init_and_join_brance_node(ret_set, (branch_node)set0->index[i], (branch_node)set1->index[i]);
|
35
|
+
} else if(set0->index[i]) {
|
36
|
+
ret_set->index[i] = (branch_node)init_and_copy_brance_node(ret_set, (branch_node)set0->index[i]);
|
37
|
+
} else if (set1->index[i]) {
|
38
|
+
ret_set->index[i] = (branch_node)init_and_copy_brance_node(ret_set, (branch_node)set1->index[i]);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
void join_branch_node(root_node root, branch_node ret_set, branch_node set0, branch_node set1)
|
45
|
+
{
|
46
|
+
int i;
|
47
|
+
|
48
|
+
if (ret_set->level == LAST_BRANCH_LEVEL) {
|
49
|
+
last_join_branch_node(root, ret_set, set0, set1);
|
50
|
+
} else {
|
51
|
+
middle_join_branch_node(root, ret_set, set0, set1);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
void middle_join_branch_node(root_node root, branch_node ret_set, branch_node set0, branch_node set1)
|
56
|
+
{
|
57
|
+
int i;
|
58
|
+
|
59
|
+
for (i = 0; i < BRANCH_NODE_SIZE; i++) {
|
60
|
+
if (set0->index[i] && set1->index[i]) {
|
61
|
+
ret_set->index[i] = (branch_node)init_and_join_brance_node(root, (branch_node)set0->index[i], (branch_node)set1->index[i]);
|
62
|
+
} else if (set0->index[i]) {
|
63
|
+
ret_set->index[i] = (branch_node)init_and_copy_brance_node(root, (branch_node)set0->index[i]);
|
64
|
+
} else if (set1->index[i]) {
|
65
|
+
ret_set->index[i] = (branch_node)init_and_copy_brance_node(root, (branch_node)set1->index[i]);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
void last_join_branch_node(root_node root, branch_node ret_set, branch_node set0, branch_node set1)
|
71
|
+
{
|
72
|
+
int i;
|
73
|
+
|
74
|
+
for (i = 0; i < BRANCH_NODE_SIZE; i++) {
|
75
|
+
if (set0->index[i] && set1->index[i]) {
|
76
|
+
ret_set->index[i] = (leaf_node)init_and_join_leaf_node(root, (leaf_node)set0->index[i], (leaf_node)set1->index[i]);
|
77
|
+
} else if (set0->index[i]) {
|
78
|
+
ret_set->index[i] = (leaf_node)init_and_copy_leaf_node(root, (leaf_node)set0->index[i]);
|
79
|
+
} else if (set1->index[i]) {
|
80
|
+
ret_set->index[i] = (leaf_node)init_and_copy_leaf_node(root, (leaf_node)set1->index[i]);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
void join_leaf_node(root_node root, leaf_node ret_set, leaf_node set0, leaf_node set1)
|
86
|
+
{
|
87
|
+
ret_set->data = set0->data | set1->data;
|
88
|
+
root->size += bit_count(ret_set->data);
|
89
|
+
}
|
90
|
+
|
91
|
+
void *init_and_join_brance_node(root_node root, branch_node set0, branch_node set1)
|
92
|
+
{
|
93
|
+
branch_node ret;
|
94
|
+
|
95
|
+
ret = init_branch_node2(set0->level, set0->num);
|
96
|
+
join_branch_node(root, ret, set0, set1);
|
97
|
+
|
98
|
+
return ret;
|
99
|
+
}
|
100
|
+
|
101
|
+
void *init_and_join_leaf_node(root_node root, leaf_node set0, leaf_node set1)
|
102
|
+
{
|
103
|
+
leaf_node ret;
|
104
|
+
|
105
|
+
ret = init_leaf_node2(set0->num);
|
106
|
+
join_leaf_node(root, ret, set0, set1);
|
107
|
+
|
108
|
+
return ret;
|
109
|
+
}
|
@@ -45,6 +45,12 @@ void *init_branch_node2(int, unsigned int);
|
|
45
45
|
void *init_leaf_node(unsigned int);
|
46
46
|
void *init_leaf_node2(unsigned int);
|
47
47
|
|
48
|
+
// init_copy
|
49
|
+
void copy_root_node(root_node, root_node);
|
50
|
+
void copy_branch_node(root_node, branch_node, branch_node);
|
51
|
+
void *init_and_copy_brance_node(root_node, branch_node);
|
52
|
+
void *init_and_copy_leaf_node(root_node, leaf_node);
|
53
|
+
|
48
54
|
// insert element into set
|
49
55
|
void add_num(root_node, unsigned int);
|
50
56
|
int search_and_insert(branch_node, int, unsigned int, unsigned int);
|
@@ -60,26 +66,43 @@ void to_array(root_node, VALUE);
|
|
60
66
|
void search_and_get_array(branch_node, VALUE);
|
61
67
|
void search_and_get_array_at_leaf(leaf_node, VALUE);
|
62
68
|
|
69
|
+
// join
|
70
|
+
void join(root_node, root_node, root_node);
|
71
|
+
void join_branch_node(root_node, branch_node, branch_node, branch_node);
|
72
|
+
void middle_join_branch_node(root_node, branch_node, branch_node, branch_node);
|
73
|
+
void last_join_branch_node(root_node, branch_node, branch_node, branch_node);
|
74
|
+
void join_leaf_node(root_node, leaf_node, leaf_node, leaf_node);
|
75
|
+
void *init_and_join_brance_node(root_node, branch_node, branch_node);
|
76
|
+
void *init_and_join_leaf_node(root_node, leaf_node, leaf_node);
|
77
|
+
|
63
78
|
// intersection
|
64
79
|
void intersection(root_node, root_node, root_node);
|
65
80
|
void intersection_branch_node(root_node, branch_node, branch_node, branch_node);
|
81
|
+
void middel_intersection_branch_node(root_node, branch_node, branch_node, branch_node);
|
82
|
+
void last_intersection_branch_node(root_node, branch_node, branch_node, branch_node);
|
66
83
|
void intersection_leaf_node(root_node, leaf_node, leaf_node, leaf_node);
|
84
|
+
void *init_and_intersection_branch_node(root_node, branch_node, branch_node);
|
67
85
|
unsigned int bit_count(unsigned int);
|
68
86
|
|
69
87
|
// memory free
|
70
88
|
void destroy_all(root_node);
|
89
|
+
void destroy_all_branches(root_node);
|
71
90
|
void destroy_branch(branch_node);
|
72
91
|
|
73
92
|
//-----------------------------------------------------------
|
74
93
|
// Ruby Methods
|
75
94
|
// ----------------------------------------------------------
|
76
95
|
|
77
|
-
static VALUE
|
96
|
+
static VALUE t_allocate(VALUE);
|
97
|
+
static VALUE t_initialize(int, VALUE *, VALUE);
|
98
|
+
static VALUE t_initialize_copy(VALUE, VALUE);
|
78
99
|
static VALUE t_add(VALUE, VALUE);
|
79
100
|
static VALUE t_delete(VALUE, VALUE);
|
80
101
|
static VALUE t_intersection(VALUE, VALUE);
|
102
|
+
static VALUE t_union(VALUE, VALUE);
|
81
103
|
static VALUE t_to_a(VALUE);
|
82
104
|
static VALUE t_size(VALUE);
|
83
105
|
static VALUE t_empty(VALUE);
|
106
|
+
static VALUE t_clear(VALUE);
|
84
107
|
void Init_rejuicer_set(void);
|
85
108
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
//************************************
|
2
|
+
// rejuicer.c
|
3
|
+
//
|
4
|
+
// Tsukasa OISHI
|
5
|
+
//
|
6
|
+
// 2010/03/17
|
7
|
+
//************************************
|
8
|
+
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <ruby.h>
|
13
|
+
#include "rejuicer_set.h"
|
14
|
+
|
15
|
+
//
|
16
|
+
// output Array object from internal set
|
17
|
+
//
|
18
|
+
void to_array(root_node root, VALUE array)
|
19
|
+
{
|
20
|
+
int i, count;
|
21
|
+
|
22
|
+
for(i = 0, count = 0; i < ROOT_NODE_SIZE || count < root->children_size; i++) {
|
23
|
+
if (root->index[i]) {
|
24
|
+
search_and_get_array((branch_node)root->index[i], array);
|
25
|
+
count++;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
void search_and_get_array(branch_node branch, VALUE array)
|
31
|
+
{
|
32
|
+
int i, count;
|
33
|
+
|
34
|
+
if (branch->level == LAST_BRANCH_LEVEL) {
|
35
|
+
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
36
|
+
if (branch->index[i]) {
|
37
|
+
search_and_get_array_at_leaf((leaf_node)branch->index[i], array);
|
38
|
+
count++;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
} else {
|
42
|
+
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
43
|
+
if (branch->index[i]) {
|
44
|
+
search_and_get_array((branch_node)branch->index[i], array);
|
45
|
+
count++;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
void search_and_get_array_at_leaf(leaf_node leaf, VALUE array)
|
52
|
+
{
|
53
|
+
int i = 0;
|
54
|
+
unsigned int x;
|
55
|
+
|
56
|
+
x = leaf->data;
|
57
|
+
|
58
|
+
while(x) {
|
59
|
+
if (x & 1) {
|
60
|
+
rb_ary_push(array, UINT2NUM(leaf->num * INDEX_PER_SIZE[LAST_BRANCH_LEVEL] + i));
|
61
|
+
}
|
62
|
+
x = x >> 1;
|
63
|
+
i++;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
//
|
69
|
+
// bit calc
|
70
|
+
//
|
71
|
+
unsigned int bit_count(unsigned int x)
|
72
|
+
{
|
73
|
+
x = x - ((x >> 1) & 0x55555555);
|
74
|
+
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
75
|
+
x = (x + (x >> 4)) & 0x0f0f0f0f;
|
76
|
+
x = x + (x >> 8);
|
77
|
+
x = x + (x >> 16);
|
78
|
+
return x & 0x0000003F;
|
79
|
+
}
|
data/lib/rejuicer.rb
CHANGED
@@ -13,7 +13,7 @@ require 'rejuicer_set'
|
|
13
13
|
# index.search(:remainder_3 => 2, :remainder_5 => 4) #=> [14,29,44,59,...,9974,9989]
|
14
14
|
#
|
15
15
|
class Rejuicer
|
16
|
-
VERSION = "0.0.
|
16
|
+
VERSION = "0.0.4"
|
17
17
|
|
18
18
|
#
|
19
19
|
# args :
|
@@ -80,15 +80,44 @@ class Rejuicer
|
|
80
80
|
# conditions: search target
|
81
81
|
#
|
82
82
|
def search(conditions = nil)
|
83
|
-
|
83
|
+
self.and(conditions).to_a
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# and
|
88
|
+
#
|
89
|
+
def and(conditions = nil)
|
90
|
+
calc_set(conditions) do |conds, f_set|
|
91
|
+
conds.sort_by{|cond| @tree[cond.first.to_sym][cond.last].size}.inject(f_set) do |work, cond|
|
92
|
+
work & @tree[cond.first.to_sym][cond.last]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# or
|
99
|
+
#
|
100
|
+
def or(conditions = nil)
|
101
|
+
calc_set(conditions) do |conds, f_set|
|
102
|
+
conds.inject(f_set) do |work, cond|
|
103
|
+
work | @tree[cond.first.to_sym][cond.last]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def size
|
109
|
+
@base.size
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def calc_set(conditions)
|
115
|
+
return @base if conditions.nil? || conditions.empty?
|
84
116
|
|
85
117
|
f_cond = conditions.shift
|
86
118
|
f_set = @tree[f_cond.first.to_sym][f_cond.last]
|
87
|
-
return f_set
|
119
|
+
return f_set if conditions.empty?
|
88
120
|
|
89
|
-
|
90
|
-
work & @tree[cond.first.to_sym][cond.last]
|
91
|
-
end
|
92
|
-
ret.to_a
|
121
|
+
yield(conditions, f_set)
|
93
122
|
end
|
94
123
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rejuicer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tsukasa OISHI
|
@@ -67,8 +67,13 @@ files:
|
|
67
67
|
- Rakefile
|
68
68
|
- lib/rejuicer.rb
|
69
69
|
- ext/extconf.rb
|
70
|
-
- ext/rejuicer_set.h
|
71
|
-
- ext/rejuicer_set.c
|
70
|
+
- ext/rejuicer_set/rejuicer_set.h
|
71
|
+
- ext/rejuicer_set/main.c
|
72
|
+
- ext/rejuicer_set/init.c
|
73
|
+
- ext/rejuicer_set/index.c
|
74
|
+
- ext/rejuicer_set/and.c
|
75
|
+
- ext/rejuicer_set/or.c
|
76
|
+
- ext/rejuicer_set/util.c
|
72
77
|
homepage: http://www.kaeruspoon.net/
|
73
78
|
licenses: []
|
74
79
|
|
data/ext/rejuicer_set.c
DELETED
@@ -1,468 +0,0 @@
|
|
1
|
-
//************************************
|
2
|
-
// rejuicer.c
|
3
|
-
//
|
4
|
-
// Tsukasa OISHI
|
5
|
-
//
|
6
|
-
// 2010/03/17
|
7
|
-
//************************************
|
8
|
-
|
9
|
-
#include <stdio.h>
|
10
|
-
#include <stdlib.h>
|
11
|
-
#include <string.h>
|
12
|
-
#include <ruby.h>
|
13
|
-
#include "rejuicer_set.h"
|
14
|
-
|
15
|
-
//
|
16
|
-
// initialize
|
17
|
-
//
|
18
|
-
void init_root_node(root_node root)
|
19
|
-
{
|
20
|
-
int i;
|
21
|
-
|
22
|
-
for(i = 0; i < ROOT_NODE_SIZE; i++) {
|
23
|
-
root->index[i] = (void*)NULL;
|
24
|
-
}
|
25
|
-
root->size = 0;
|
26
|
-
root->children_size = 0;
|
27
|
-
}
|
28
|
-
|
29
|
-
void *init_branch_node(int level, unsigned int value)
|
30
|
-
{
|
31
|
-
return init_branch_node2(level, (value / INDEX_PER_SIZE[level - 1]));
|
32
|
-
}
|
33
|
-
|
34
|
-
void *init_branch_node2(int level, unsigned int num)
|
35
|
-
{
|
36
|
-
int i;
|
37
|
-
branch_node branch;
|
38
|
-
|
39
|
-
if (!(branch = (branch_node)malloc(sizeof(struct _branch_node)))) {
|
40
|
-
rb_raise(rb_eStandardError, "memory is not enough");
|
41
|
-
}
|
42
|
-
|
43
|
-
for(i = 0; i < BRANCH_NODE_SIZE; i++) {
|
44
|
-
branch->index[i] = (void*)NULL;
|
45
|
-
}
|
46
|
-
|
47
|
-
branch->level = level;
|
48
|
-
branch->num = num;
|
49
|
-
branch->children_size = 0;
|
50
|
-
|
51
|
-
return (void*)branch;
|
52
|
-
}
|
53
|
-
|
54
|
-
void *init_leaf_node(unsigned int value)
|
55
|
-
{
|
56
|
-
return init_leaf_node2(value / INDEX_PER_SIZE[LAST_BRANCH_LEVEL]);
|
57
|
-
}
|
58
|
-
|
59
|
-
void *init_leaf_node2(unsigned int num)
|
60
|
-
{
|
61
|
-
leaf_node leaf;
|
62
|
-
|
63
|
-
if(!(leaf = (leaf_node)malloc(sizeof(struct _leaf_node)))) {
|
64
|
-
rb_raise(rb_eStandardError, "memory is not enough");
|
65
|
-
}
|
66
|
-
|
67
|
-
leaf->num = num;
|
68
|
-
leaf->data = 0;
|
69
|
-
|
70
|
-
return (void*)leaf;
|
71
|
-
}
|
72
|
-
|
73
|
-
//
|
74
|
-
// insert element into set
|
75
|
-
//
|
76
|
-
void add_num(root_node root, unsigned int value)
|
77
|
-
{
|
78
|
-
unsigned int quotient, remainder;
|
79
|
-
|
80
|
-
quotient = value / INDEX_PER_SIZE[0];
|
81
|
-
remainder = value % INDEX_PER_SIZE[0];
|
82
|
-
|
83
|
-
if(!(root->index[quotient])) {
|
84
|
-
root->index[quotient] = init_branch_node(1, quotient);
|
85
|
-
root->children_size++;
|
86
|
-
}
|
87
|
-
|
88
|
-
if (search_and_insert((branch_node)root->index[quotient], 1, remainder, value)) {
|
89
|
-
root->size++;
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
int search_and_insert(branch_node branch, int level, unsigned int value, unsigned int original)
|
94
|
-
{
|
95
|
-
unsigned int quotient, remainder;
|
96
|
-
|
97
|
-
quotient = value / INDEX_PER_SIZE[level];
|
98
|
-
remainder = value % INDEX_PER_SIZE[level];
|
99
|
-
|
100
|
-
if(!(branch->index[quotient])) {
|
101
|
-
branch->children_size++;
|
102
|
-
if(level == LAST_BRANCH_LEVEL) {
|
103
|
-
branch->index[quotient] = init_leaf_node(original);
|
104
|
-
} else {
|
105
|
-
branch->index[quotient] = init_branch_node(level + 1, original);
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
if (level == LAST_BRANCH_LEVEL) {
|
110
|
-
return search_and_insert_at_leaf((leaf_node)branch->index[quotient], remainder);
|
111
|
-
} else {
|
112
|
-
return search_and_insert((branch_node)branch->index[quotient], level + 1, remainder, original);
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
int search_and_insert_at_leaf(leaf_node leaf, unsigned int value)
|
117
|
-
{
|
118
|
-
int exist_flag = 0;
|
119
|
-
unsigned int target_bit;
|
120
|
-
|
121
|
-
target_bit = 1 << value;
|
122
|
-
|
123
|
-
if (!(leaf->data & target_bit)) {
|
124
|
-
leaf->data |= target_bit;
|
125
|
-
exist_flag = 1;
|
126
|
-
}
|
127
|
-
|
128
|
-
return exist_flag;
|
129
|
-
}
|
130
|
-
|
131
|
-
//
|
132
|
-
// remove element from set
|
133
|
-
//
|
134
|
-
void delete_num(root_node root, unsigned int value)
|
135
|
-
{
|
136
|
-
unsigned int quotient, remainder;
|
137
|
-
|
138
|
-
quotient = value / INDEX_PER_SIZE[0];
|
139
|
-
remainder = value % INDEX_PER_SIZE[0];
|
140
|
-
|
141
|
-
if (!(root->index[quotient])) return;
|
142
|
-
|
143
|
-
if (search_and_remove((branch_node)root->index[quotient], 1, remainder, value)) {
|
144
|
-
root->size--;
|
145
|
-
}
|
146
|
-
}
|
147
|
-
|
148
|
-
int search_and_remove(branch_node branch, int level, unsigned int value, unsigned int original)
|
149
|
-
{
|
150
|
-
unsigned int quotient, remainder, result;
|
151
|
-
|
152
|
-
quotient = value / INDEX_PER_SIZE[level];
|
153
|
-
remainder = value % INDEX_PER_SIZE[level];
|
154
|
-
|
155
|
-
if (!(branch->index[quotient])) return;
|
156
|
-
|
157
|
-
if (level == LAST_BRANCH_LEVEL) {
|
158
|
-
return search_and_remove_at_leaf((leaf_node)branch->index[quotient], remainder);
|
159
|
-
} else {
|
160
|
-
return search_and_remove((branch_node)branch->index[quotient], level + 1, remainder, original);
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
int search_and_remove_at_leaf(leaf_node leaf, unsigned int value)
|
165
|
-
{
|
166
|
-
int exist_flag = 0;
|
167
|
-
unsigned int target_bit;
|
168
|
-
|
169
|
-
target_bit = 1 << value;
|
170
|
-
|
171
|
-
if ((leaf->data & target_bit)) {
|
172
|
-
leaf->data ^= target_bit;
|
173
|
-
exist_flag = 1;
|
174
|
-
}
|
175
|
-
|
176
|
-
return exist_flag;
|
177
|
-
}
|
178
|
-
|
179
|
-
//
|
180
|
-
// output Array object from internal set
|
181
|
-
//
|
182
|
-
void to_array(root_node root, VALUE array)
|
183
|
-
{
|
184
|
-
int i, count;
|
185
|
-
|
186
|
-
for(i = 0, count = 0; i < ROOT_NODE_SIZE || count < root->children_size; i++) {
|
187
|
-
if (root->index[i]) {
|
188
|
-
search_and_get_array((branch_node)root->index[i], array);
|
189
|
-
count++;
|
190
|
-
}
|
191
|
-
}
|
192
|
-
}
|
193
|
-
|
194
|
-
void search_and_get_array(branch_node branch, VALUE array)
|
195
|
-
{
|
196
|
-
int i, count;
|
197
|
-
|
198
|
-
if (branch->level == LAST_BRANCH_LEVEL) {
|
199
|
-
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
200
|
-
if (branch->index[i]) {
|
201
|
-
search_and_get_array_at_leaf((leaf_node)branch->index[i], array);
|
202
|
-
count++;
|
203
|
-
}
|
204
|
-
}
|
205
|
-
} else {
|
206
|
-
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
207
|
-
if (branch->index[i]) {
|
208
|
-
search_and_get_array((branch_node)branch->index[i], array);
|
209
|
-
count++;
|
210
|
-
}
|
211
|
-
}
|
212
|
-
}
|
213
|
-
}
|
214
|
-
|
215
|
-
void search_and_get_array_at_leaf(leaf_node leaf, VALUE array)
|
216
|
-
{
|
217
|
-
int i = 0;
|
218
|
-
unsigned int x;
|
219
|
-
|
220
|
-
x = leaf->data;
|
221
|
-
|
222
|
-
while(x) {
|
223
|
-
if (x & 1) {
|
224
|
-
rb_ary_push(array, UINT2NUM(leaf->num * INDEX_PER_SIZE[LAST_BRANCH_LEVEL] + i));
|
225
|
-
}
|
226
|
-
x = x >> 1;
|
227
|
-
i++;
|
228
|
-
}
|
229
|
-
}
|
230
|
-
|
231
|
-
//
|
232
|
-
// intersection
|
233
|
-
//
|
234
|
-
void intersection(root_node ret_set, root_node set0, root_node set1)
|
235
|
-
{
|
236
|
-
int i, count;
|
237
|
-
root_node base, other;
|
238
|
-
|
239
|
-
if (set0->size == 0 || set1->size == 0) {
|
240
|
-
return;
|
241
|
-
} else if (set0->size > set1->size) {
|
242
|
-
base = set1;
|
243
|
-
other = set0;
|
244
|
-
} else {
|
245
|
-
base = set0;
|
246
|
-
other = set1;
|
247
|
-
}
|
248
|
-
|
249
|
-
for (i = 0, count = 0; i < ROOT_NODE_SIZE || count < base->children_size; i++) {
|
250
|
-
if (base->index[i]) {
|
251
|
-
count++;
|
252
|
-
if (other->index[i]) {
|
253
|
-
ret_set->index[i] = init_branch_node2(((branch_node)base->index[i])->level, ((branch_node)base->index[i])->num);
|
254
|
-
intersection_branch_node(ret_set, (branch_node)ret_set->index[i], (branch_node)base->index[i], (branch_node)other->index[i]);
|
255
|
-
}
|
256
|
-
}
|
257
|
-
}
|
258
|
-
}
|
259
|
-
|
260
|
-
void intersection_branch_node(root_node root, branch_node ret_set, branch_node base, branch_node other)
|
261
|
-
{
|
262
|
-
int i, count;
|
263
|
-
|
264
|
-
for (i = 0, count = 0; i < BRANCH_NODE_SIZE || count < base->children_size; i++) {
|
265
|
-
if (base->index[i]) {
|
266
|
-
count++;
|
267
|
-
if (other->index[i]) {
|
268
|
-
if (base->level == LAST_BRANCH_LEVEL) {
|
269
|
-
ret_set->index[i] = init_leaf_node2(((leaf_node)base->index[i])->num);
|
270
|
-
intersection_leaf_node(root, (leaf_node)ret_set->index[i], (leaf_node)base->index[i], (leaf_node)other->index[i]);
|
271
|
-
} else {
|
272
|
-
ret_set->index[i] = init_branch_node2(((branch_node)base->index[i])->level, ((branch_node)base->index[i])->num);
|
273
|
-
intersection_branch_node(root, (branch_node)ret_set->index[i], (branch_node)base->index[i], (branch_node)other->index[i]);
|
274
|
-
}
|
275
|
-
}
|
276
|
-
}
|
277
|
-
}
|
278
|
-
}
|
279
|
-
|
280
|
-
void intersection_leaf_node(root_node root, leaf_node ret_set, leaf_node base, leaf_node other)
|
281
|
-
{
|
282
|
-
ret_set->data = base->data & other->data;
|
283
|
-
root->size += bit_count(ret_set->data);
|
284
|
-
}
|
285
|
-
|
286
|
-
unsigned int bit_count(unsigned int x)
|
287
|
-
{
|
288
|
-
x = x - ((x >> 1) & 0x55555555);
|
289
|
-
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
290
|
-
x = (x + (x >> 4)) & 0x0f0f0f0f;
|
291
|
-
x = x + (x >> 8);
|
292
|
-
x = x + (x >> 16);
|
293
|
-
return x & 0x0000003F;
|
294
|
-
}
|
295
|
-
|
296
|
-
//
|
297
|
-
// memory free
|
298
|
-
//
|
299
|
-
void destroy_all(root_node root)
|
300
|
-
{
|
301
|
-
int i, count;
|
302
|
-
|
303
|
-
for(i = 0, count = 0; i < ROOT_NODE_SIZE || count < root->children_size; i++) {
|
304
|
-
if (root->index[i]) {
|
305
|
-
destroy_branch((branch_node)root->index[i]);
|
306
|
-
count++;
|
307
|
-
}
|
308
|
-
}
|
309
|
-
free(root);
|
310
|
-
}
|
311
|
-
|
312
|
-
void destroy_branch(branch_node branch)
|
313
|
-
{
|
314
|
-
int i, count;
|
315
|
-
|
316
|
-
if (branch->level == LAST_BRANCH_LEVEL) {
|
317
|
-
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
318
|
-
if (branch->index[i]) {
|
319
|
-
free((leaf_node)branch->index[i]);
|
320
|
-
branch->index[i] = NULL;
|
321
|
-
count++;
|
322
|
-
}
|
323
|
-
}
|
324
|
-
} else {
|
325
|
-
for(i = 0, count = 0; i < BRANCH_NODE_SIZE || count < branch->children_size; i++) {
|
326
|
-
if (branch->index[i]) {
|
327
|
-
destroy_branch((branch_node)branch->index[i]);
|
328
|
-
branch->index[i] = NULL;
|
329
|
-
count++;
|
330
|
-
}
|
331
|
-
}
|
332
|
-
}
|
333
|
-
free(branch);
|
334
|
-
}
|
335
|
-
|
336
|
-
//-----------------------------------------------------------
|
337
|
-
// Ruby Methods
|
338
|
-
// ----------------------------------------------------------
|
339
|
-
|
340
|
-
/**
|
341
|
-
* new
|
342
|
-
**/
|
343
|
-
static VALUE t_new(int argc, VALUE *argv, VALUE klass)
|
344
|
-
{
|
345
|
-
VALUE num;
|
346
|
-
VALUE obj;
|
347
|
-
root_node root;
|
348
|
-
|
349
|
-
obj = Data_Make_Struct(klass, struct _root_node, NULL, destroy_all, root);
|
350
|
-
init_root_node(root);
|
351
|
-
|
352
|
-
if (argc == 1) {
|
353
|
-
while((num = rb_ary_shift(argv[0])) != Qnil) {
|
354
|
-
add_num(root, NUM2UINT(num));
|
355
|
-
}
|
356
|
-
}
|
357
|
-
|
358
|
-
return obj;
|
359
|
-
}
|
360
|
-
|
361
|
-
/**
|
362
|
-
* add
|
363
|
-
**/
|
364
|
-
static VALUE t_add(VALUE self, VALUE value)
|
365
|
-
{
|
366
|
-
root_node root;
|
367
|
-
unsigned int num;
|
368
|
-
|
369
|
-
Data_Get_Struct(self, struct _root_node, root);
|
370
|
-
add_num(root, NUM2UINT(value));
|
371
|
-
|
372
|
-
return self;
|
373
|
-
}
|
374
|
-
|
375
|
-
/**
|
376
|
-
* delete
|
377
|
-
**/
|
378
|
-
static VALUE t_delete(VALUE self, VALUE value)
|
379
|
-
{
|
380
|
-
root_node root;
|
381
|
-
unsigned int num;
|
382
|
-
|
383
|
-
Data_Get_Struct(self, struct _root_node, root);
|
384
|
-
delete_num(root, NUM2UINT(value));
|
385
|
-
|
386
|
-
return self;
|
387
|
-
}
|
388
|
-
|
389
|
-
/**
|
390
|
-
* intersection
|
391
|
-
**/
|
392
|
-
static VALUE t_intersection(VALUE self, VALUE array)
|
393
|
-
{
|
394
|
-
root_node set0, set1, ret_set;
|
395
|
-
VALUE ret;
|
396
|
-
|
397
|
-
ret = Data_Make_Struct(rb_cRejuicerSet, struct _root_node, NULL, destroy_all, ret_set);
|
398
|
-
init_root_node(ret_set);
|
399
|
-
|
400
|
-
Data_Get_Struct(self, struct _root_node, set0);
|
401
|
-
Data_Get_Struct(array, struct _root_node, set1);
|
402
|
-
|
403
|
-
intersection(ret_set, set0, set1);
|
404
|
-
|
405
|
-
return ret;
|
406
|
-
}
|
407
|
-
|
408
|
-
/**
|
409
|
-
* to_a
|
410
|
-
**/
|
411
|
-
static VALUE t_to_a(VALUE self)
|
412
|
-
{
|
413
|
-
int i;
|
414
|
-
root_node root;
|
415
|
-
VALUE array;
|
416
|
-
|
417
|
-
Data_Get_Struct(self, struct _root_node, root);
|
418
|
-
array = rb_ary_new2(root->size);
|
419
|
-
|
420
|
-
to_array(root, array);
|
421
|
-
|
422
|
-
return array;
|
423
|
-
}
|
424
|
-
|
425
|
-
/**
|
426
|
-
* size
|
427
|
-
**/
|
428
|
-
static VALUE t_size(VALUE self)
|
429
|
-
{
|
430
|
-
root_node root;
|
431
|
-
|
432
|
-
Data_Get_Struct(self, struct _root_node, root);
|
433
|
-
|
434
|
-
return INT2NUM(root->size);
|
435
|
-
}
|
436
|
-
|
437
|
-
/**
|
438
|
-
* empty?
|
439
|
-
**/
|
440
|
-
static VALUE t_empty(VALUE self)
|
441
|
-
{
|
442
|
-
root_node root;
|
443
|
-
|
444
|
-
Data_Get_Struct(self, struct _root_node, root);
|
445
|
-
|
446
|
-
if (root->size == 0) {
|
447
|
-
return Qtrue;
|
448
|
-
} else {
|
449
|
-
return Qfalse;
|
450
|
-
}
|
451
|
-
}
|
452
|
-
|
453
|
-
/**
|
454
|
-
* define class
|
455
|
-
**/
|
456
|
-
void Init_rejuicer_set(void) {
|
457
|
-
rb_cRejuicerSet = rb_define_class("RejuicerSet", rb_cObject);
|
458
|
-
rb_define_singleton_method(rb_cRejuicerSet, "new", t_new, -1);
|
459
|
-
rb_define_method(rb_cRejuicerSet, "add", t_add, 1);
|
460
|
-
rb_define_method(rb_cRejuicerSet, "delete", t_delete, 1);
|
461
|
-
rb_define_method(rb_cRejuicerSet, "intersection", t_intersection, 1);
|
462
|
-
rb_define_method(rb_cRejuicerSet, "to_a", t_to_a, 0);
|
463
|
-
rb_define_method(rb_cRejuicerSet, "size", t_size, 0);
|
464
|
-
rb_define_method(rb_cRejuicerSet, "empty?", t_empty, 0);
|
465
|
-
rb_define_alias(rb_cRejuicerSet, "<<", "add");
|
466
|
-
rb_define_alias(rb_cRejuicerSet, "&", "intersection");
|
467
|
-
rb_define_alias(rb_cRejuicerSet, "length", "size");
|
468
|
-
}
|