figure_set 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2012-11-26
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,14 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/figure_set.rb
6
+ ext/extconf.rb
7
+ ext/figure_set.h
8
+ ext/methods.c
9
+ ext/init.c
10
+ ext/index.c
11
+ ext/and.c
12
+ ext/or.c
13
+ ext/array.c
14
+ ext/sample.c
data/README.rdoc ADDED
@@ -0,0 +1,61 @@
1
+ = FigureSet
2
+
3
+ = Description
4
+ FigureSet is the library which treats set operation.
5
+ FigureSet is able to treat the set of 32bit integer.(0 .. 2 ** 32 -1)
6
+
7
+ = How to
8
+
9
+ == Initialize
10
+ === an empty set.
11
+ empty_set = FigureSet.new
12
+
13
+ === give array.
14
+ set = FigureSet.new([0,3,6,7])
15
+
16
+ == Element operation
17
+ === add to set.
18
+ set = FigureSet.new
19
+ set.add 10
20
+ set << 100
21
+ set.to_a #=> [10, 100]
22
+
23
+ === remove from set.
24
+ set = FigureSet.new([1,4,5])
25
+ set.delete(4)
26
+ set.to_a #=> [1, 5]
27
+
28
+ == Set operation
29
+ === and
30
+ set1 = FigureSet.new([1,2,3,5])
31
+ set2 = FigureSet.new([2,4,6])
32
+ set_and = set1 & set2
33
+ set_and.to_a #=> [2]
34
+
35
+ === or
36
+ set1 = FigureSet.new([1,2,3,5])
37
+ set2 = FigureSet.new([2,4,6])
38
+ set_or = set1 | set2
39
+ set_or.to_a #=> [1,2,3,4,5,6]
40
+
41
+ == Other
42
+ === size
43
+ set = FigureSet.new([1,2,3])
44
+ set.size #=> 3
45
+
46
+ === empty?
47
+ set = FigureSet.new
48
+ set.empty? #=> true
49
+
50
+ === clear
51
+ set = FigureSet.new([1,2,3])
52
+ set.clear
53
+ set.to_a #=> []
54
+
55
+ = INSTALL:
56
+
57
+ sudo gem install figure_set
58
+
59
+ = LICENSE:
60
+
61
+ FigureSet is released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/figure_set'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('figure_set', FigureSet.version) do |p|
7
+ p.developer('Tsukasa OISHI', 'tsukasa.oishi@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name # TODO this is default value
10
+ p.extra_dev_deps = [
11
+ ['newgem', ">= #{::Newgem::VERSION}"]
12
+ ]
13
+
14
+ pec_extras = {
15
+ :extensions => ['ext/extconf.rb'],
16
+ }
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
data/ext/and.c ADDED
@@ -0,0 +1,118 @@
1
+ //************************************
2
+ // and.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //
12
+ // intersection
13
+ //
14
+ void intersection(root_node result_set, root_node set0, root_node set1)
15
+ {
16
+ unsigned int i, count;
17
+ root_node base, other;
18
+ branch_node branch;
19
+
20
+ if (set0->size == 0 || set1->size == 0) {
21
+ return;
22
+ } else if (set0->size > set1->size) {
23
+ base = set1;
24
+ other = set0;
25
+ } else {
26
+ base = set0;
27
+ other = set1;
28
+ }
29
+
30
+ for (i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE || count < base->children_size; i++) {
31
+ if (base->index[i]) {
32
+ count++;
33
+ if (other->index[i]) {
34
+ branch = (branch_node)init_and_intersection_branch_node(result_set, (branch_node)base->index[i], (branch_node)other->index[i]);
35
+ if (branch) {
36
+ result_set->index[i] = (void*)branch;
37
+ result_set->children_size++;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ void *init_and_intersection_branch_node(root_node result_set, branch_node base, branch_node other)
45
+ {
46
+ branch_node branch;
47
+
48
+ branch = (branch_node)init_branch_node();
49
+
50
+ if (base->children_type == CT_LEAF) {
51
+ last_intersection_branch_node(result_set, branch, base, other);
52
+ } else {
53
+ middel_intersection_branch_node(result_set, branch, base, other);
54
+ }
55
+
56
+ if (branch->children_size) {
57
+ branch->children_type = base->children_type;
58
+ return (void*)branch;
59
+ } else {
60
+ destroy_branch(branch);
61
+ return (void*)NULL;
62
+ }
63
+ }
64
+
65
+ void middel_intersection_branch_node(root_node result_set, branch_node branch, branch_node base, branch_node other)
66
+ {
67
+ unsigned int i, count;
68
+ branch_node middle_branch;
69
+
70
+ for (i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < base->children_size; i++) {
71
+ if (base->index[i]) {
72
+ count++;
73
+ if (other->index[i]) {
74
+ middle_branch = (branch_node)init_and_intersection_branch_node(result_set, (branch_node)base->index[i], (branch_node)other->index[i]);
75
+ if (middle_branch) {
76
+ branch->index[i] = (void*)middle_branch;
77
+ branch->children_size++;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ void last_intersection_branch_node(root_node result_set, branch_node branch, branch_node base, branch_node other)
85
+ {
86
+ unsigned int i, count;
87
+ leaf_node leaf;
88
+
89
+ for (i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < base->children_size; i++) {
90
+ if (base->index[i]) {
91
+ count++;
92
+ if (other->index[i]) {
93
+ leaf = (leaf_node)init_and_intersection_leaf_node(result_set, (leaf_node)base->index[i], (leaf_node)other->index[i]);
94
+ if (leaf) {
95
+ branch->index[i] = (void*)leaf;
96
+ branch->children_size++;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+
104
+ void *init_and_intersection_leaf_node(root_node result_set, leaf_node base, leaf_node other)
105
+ {
106
+ unsigned long data;
107
+ leaf_node leaf;
108
+
109
+ data = base->data & other->data;
110
+
111
+ if (!data) return (void*)NULL;
112
+
113
+ leaf = (leaf_node)init_leaf_node(base->offset);
114
+ leaf->data = data;
115
+ result_set->size += BIT_COUNT(leaf->data);
116
+
117
+ return (void*)leaf;
118
+ }
data/ext/array.c ADDED
@@ -0,0 +1,98 @@
1
+ //************************************
2
+ // array.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //
12
+ // output Array object from internal set
13
+ //
14
+ void to_array(root_node root, VALUE array)
15
+ {
16
+ unsigned int i, count;
17
+
18
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE || count < root->children_size; i++) {
19
+ if (root->index[i]) {
20
+ search_and_get_array((branch_node)root->index[i], array);
21
+ count++;
22
+ }
23
+ }
24
+ }
25
+
26
+ void search_and_get_array(branch_node branch, VALUE array)
27
+ {
28
+ unsigned int i, count;
29
+
30
+ if (branch->children_type == CT_LEAF) {
31
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < branch->children_size; i++) {
32
+ if (branch->index[i]) {
33
+ search_and_get_array_at_leaf((leaf_node)branch->index[i], array);
34
+ count++;
35
+ }
36
+ }
37
+ } else {
38
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < branch->children_size; i++) {
39
+ if (branch->index[i]) {
40
+ search_and_get_array((branch_node)branch->index[i], array);
41
+ count++;
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ void search_and_get_array_at_leaf(leaf_node leaf, VALUE array)
48
+ {
49
+ unsigned long i = 0;
50
+ unsigned long x;
51
+
52
+ x = leaf->data;
53
+
54
+ while(x) {
55
+ i = BIT_COUNT((x & (-x))-1);
56
+ rb_ary_push(array, ULONG2NUM(leaf->offset + i));
57
+ x = x ^ (1UL << i);
58
+ }
59
+
60
+
61
+ /*
62
+ while(x) {
63
+ if (x & 1UL) {
64
+ rb_ary_push(array, ULONG2NUM(leaf->offset + i));
65
+ }
66
+ x = x >> 1UL;
67
+ i++;
68
+ }
69
+ */
70
+ }
71
+
72
+
73
+ //
74
+ // bit count
75
+ //
76
+
77
+ // 32 bit
78
+ unsigned long bit32_count(unsigned long x)
79
+ {
80
+ x = x - ((x >> 1UL) & 0x55555555UL);
81
+ x = (x & 0x33333333UL) + ((x >> 2UL) & 0x33333333UL);
82
+ x = (x + (x >> 4UL)) & 0x0f0f0f0fUL;
83
+ x = x + (x >> 8UL);
84
+ x = x + (x >> 16UL);
85
+ return x & 0x0000003FUL;
86
+ }
87
+
88
+ // 64 bit
89
+ unsigned long bit64_count(unsigned long x)
90
+ {
91
+ x = x - ((x >> 1UL) & 0x5555555555555555UL);
92
+ x = (x & 0x3333333333333333UL) + ((x >> 2UL) & 0x3333333333333333UL);
93
+ x = (x & 0x0f0f0f0f0f0f0f0fUL) + ((x >> 4UL) & 0x0f0f0f0f0f0f0f0fUL);
94
+ x = (x + (x >> 8UL)) & 0x00ff00ff00ff00ffUL;
95
+ x = x + (x >> 16UL);
96
+ x = x + (x >> 32UL);
97
+ return x & 0x000000000000007FUL;
98
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "mkmf"
2
+ create_makefile("figure_set")
data/ext/figure_set.h ADDED
@@ -0,0 +1,145 @@
1
+ //************************************
2
+ // figure_set.h
3
+ //
4
+ // Tsukasa OISHI
5
+ // http://www.kaeruspoon.net
6
+ //************************************
7
+
8
+ #include <math.h>
9
+
10
+ #ifndef RUBY_19
11
+ #ifndef RFLOAT_VALUE
12
+ #define RFLOAT_VALUE(v) (RFLOAT(v)->value)
13
+ #endif
14
+ #ifndef RARRAY_LEN
15
+ #define RARRAY_LEN(v) (RARRAY(v)->len)
16
+ #endif
17
+ #ifndef RARRAY_PTR
18
+ #define RARRAY_PTR(v) (RARRAY(v)->ptr)
19
+ #endif
20
+ #endif
21
+
22
+ // max children size of branch
23
+ #define MAX_CHILDREN_SIZE_OF_BRANCH (unsigned long)16
24
+ #define LAST_BRANCH_LEVEL (unsigned long)6
25
+
26
+ #if ULLONG_MAX == 0xffffffffffffffff
27
+ #define ULONG_BIT_COUNT (unsigned long)64
28
+ #define MAX_CHILDREN_SIZE_OF_ROOT_NODE (unsigned long)4
29
+ #define BIT_COUNT(x) bit64_count(x)
30
+ static unsigned long OFFSET_SCALE[] = {0x40000000, 0x4000000, 0x400000, 0x40000, 0x4000, 0x400, 0x40};
31
+ #else
32
+ #define ULONG_BIT_COUNT (unsigned long)32
33
+ #define MAX_CHILDREN_SIZE_OF_ROOT_NODE (unsigned long)8
34
+ #define BIT_COUNT(x) bit32_count(x)
35
+ static unsigned long OFFSET_SCALE[] = {0x20000000, 0x2000000, 0x200000, 0x20000, 0x2000, 0x200, 0x20};
36
+ #endif
37
+
38
+ // branch node children type
39
+ #define CT_BRANCH 0
40
+ #define CT_LEAF 1
41
+
42
+ // valid valie range
43
+ #define VALID_MIN_VALUE UINT2NUM(0)
44
+ #define VALID_MAX_VALUE UINT2NUM(0xffffffff)
45
+
46
+ // FigureSet class object
47
+ static VALUE rb_cFigureSet;
48
+
49
+ // leaf node
50
+ // example:
51
+ // data = 5 # (bit is 0...0101) exist bit numbers is (2, 0)
52
+ // offset = 640
53
+ //
54
+ // set is
55
+ // [offset + 2, offset + 0]
56
+ // = [642, 640]
57
+ //
58
+ typedef struct _leaf_node {
59
+ unsigned long offset; // offset number
60
+ unsigned long data; // each bit is exist flag(1:exist 0:none) of member
61
+ } *leaf_node;
62
+
63
+ // branch node
64
+ typedef struct _branch_node {
65
+ unsigned char children_type; // children type
66
+ unsigned char children_size;
67
+ void *index[MAX_CHILDREN_SIZE_OF_BRANCH]; // children pointer
68
+ } *branch_node;
69
+
70
+ typedef struct _root_node {
71
+ unsigned char children_size;
72
+ unsigned long size; // number of elements in set
73
+ void *index[MAX_CHILDREN_SIZE_OF_ROOT_NODE]; // children pointer
74
+ } *root_node;
75
+
76
+ // initialize
77
+ void init_root_node(root_node);
78
+ void *init_branch_node();
79
+ void *init_leaf_node(unsigned long);
80
+
81
+ // init_copy
82
+ void copy_root_node(root_node, root_node);
83
+ void copy_branch_node(root_node, branch_node, branch_node);
84
+ void *init_and_copy_brance_node(root_node, branch_node);
85
+ void *init_and_copy_leaf_node(root_node, leaf_node);
86
+
87
+ // insert element into set
88
+ void add_num(root_node, unsigned long);
89
+ unsigned int search_and_insert(branch_node, unsigned long, unsigned long, unsigned long);
90
+ unsigned int search_and_insert_at_leaf(leaf_node, unsigned long);
91
+
92
+ // remove element from set
93
+ void delete_num(root_node, unsigned long);
94
+ unsigned int search_and_remove(branch_node, unsigned long, unsigned long, unsigned long);
95
+ unsigned int search_and_remove_at_leaf(leaf_node, unsigned long);
96
+
97
+ // output Array object from internal set
98
+ void to_array(root_node, VALUE);
99
+ void search_and_get_array(branch_node, VALUE);
100
+ void search_and_get_array_at_leaf(leaf_node, VALUE);
101
+
102
+ // join
103
+ void join(root_node, root_node, root_node);
104
+ void middle_join_branch_node(root_node, branch_node, branch_node, branch_node);
105
+ void last_join_branch_node(root_node, branch_node, branch_node, branch_node);
106
+ void *init_and_join_brance_node(root_node, branch_node, branch_node);
107
+ void *init_and_join_leaf_node(root_node, leaf_node, leaf_node);
108
+
109
+ // intersection
110
+ void intersection(root_node, root_node, root_node);
111
+ void middel_intersection_branch_node(root_node, branch_node, branch_node, branch_node);
112
+ void last_intersection_branch_node(root_node, branch_node, branch_node, branch_node);
113
+ void *init_and_intersection_leaf_node(root_node, leaf_node, leaf_node);
114
+ void *init_and_intersection_branch_node(root_node, branch_node, branch_node);
115
+ unsigned long bit32_count(unsigned long);
116
+ unsigned long bit64_count(unsigned long);
117
+
118
+ // sample
119
+ void sample(root_node, VALUE, unsigned long);
120
+ void search_and_sample_array(branch_node, VALUE);
121
+ void search_and_sample_array_at_leaf(leaf_node, VALUE);
122
+
123
+ // memory free
124
+ void destroy_all(root_node);
125
+ void destroy_all_branches(root_node);
126
+ void destroy_branch(branch_node);
127
+
128
+ //-----------------------------------------------------------
129
+ // Ruby Methods
130
+ // ----------------------------------------------------------
131
+
132
+ static VALUE t_allocate(VALUE);
133
+ static VALUE t_initialize(int, VALUE *, VALUE);
134
+ static VALUE t_initialize_copy(VALUE, VALUE);
135
+ static VALUE t_add(VALUE, VALUE);
136
+ static VALUE t_delete(VALUE, VALUE);
137
+ static VALUE t_intersection(VALUE, VALUE);
138
+ static VALUE t_union(VALUE, VALUE);
139
+ static VALUE t_to_a(VALUE);
140
+ static VALUE t_sample(int, VALUE *, VALUE);
141
+ static VALUE t_size(VALUE);
142
+ static VALUE t_empty(VALUE);
143
+ static VALUE t_clear(VALUE);
144
+ void Init_figure_set(void);
145
+
data/ext/index.c ADDED
@@ -0,0 +1,118 @@
1
+ //************************************
2
+ // index.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //
12
+ // insert element into set
13
+ //
14
+ void add_num(root_node root, unsigned long value)
15
+ {
16
+ unsigned long quotient, remainder;
17
+
18
+ quotient = value / OFFSET_SCALE[0];
19
+ remainder = value % OFFSET_SCALE[0];
20
+
21
+ if(!(root->index[quotient])) {
22
+ root->index[quotient] = init_branch_node();
23
+ root->children_size++;
24
+ }
25
+
26
+ if (search_and_insert((branch_node)root->index[quotient], 1, remainder, value)) {
27
+ root->size++;
28
+ }
29
+ }
30
+
31
+ unsigned int search_and_insert(branch_node branch, unsigned long level, unsigned long value, unsigned long original)
32
+ {
33
+ unsigned long quotient, remainder;
34
+
35
+ quotient = value / OFFSET_SCALE[level];
36
+ remainder = value % OFFSET_SCALE[level];
37
+
38
+ if(!(branch->index[quotient])) {
39
+ if(branch->children_type == CT_LEAF) {
40
+ branch->index[quotient] = init_leaf_node((unsigned long)(original / ULONG_BIT_COUNT) * ULONG_BIT_COUNT);
41
+ } else {
42
+ branch->index[quotient] = init_branch_node();
43
+ if ((level + 1) == LAST_BRANCH_LEVEL) {
44
+ ((branch_node)(branch->index[quotient]))->children_type = CT_LEAF;
45
+ }
46
+ }
47
+ branch->children_size++;
48
+ }
49
+
50
+ if (branch->children_type == CT_LEAF) {
51
+ return search_and_insert_at_leaf((leaf_node)branch->index[quotient], remainder);
52
+ } else {
53
+ return search_and_insert((branch_node)branch->index[quotient], level + 1, remainder, original);
54
+ }
55
+ }
56
+
57
+ unsigned int search_and_insert_at_leaf(leaf_node leaf, unsigned long value)
58
+ {
59
+ unsigned int exist_flag = 0;
60
+ unsigned long target_bit;
61
+
62
+ target_bit = 1UL << value;
63
+
64
+ if (!(leaf->data & target_bit)) {
65
+ leaf->data |= target_bit;
66
+ exist_flag = 1;
67
+ }
68
+
69
+ return exist_flag;
70
+ }
71
+
72
+ //
73
+ // remove element from set
74
+ //
75
+ void delete_num(root_node root, unsigned long value)
76
+ {
77
+ unsigned long quotient, remainder;
78
+
79
+ quotient = value / OFFSET_SCALE[0];
80
+ remainder = value % OFFSET_SCALE[0];
81
+
82
+ if (!(root->index[quotient])) return;
83
+
84
+ if (search_and_remove((branch_node)root->index[quotient], 1, remainder, value)) {
85
+ root->size--;
86
+ }
87
+ }
88
+
89
+ unsigned int search_and_remove(branch_node branch, unsigned long level, unsigned long value, unsigned long original)
90
+ {
91
+ unsigned long quotient, remainder;
92
+
93
+ quotient = value / OFFSET_SCALE[level];
94
+ remainder = value % OFFSET_SCALE[level];
95
+
96
+ if (!(branch->index[quotient])) return 0;
97
+
98
+ if (branch->children_type == CT_LEAF) {
99
+ return search_and_remove_at_leaf((leaf_node)branch->index[quotient], remainder);
100
+ } else {
101
+ return search_and_remove((branch_node)branch->index[quotient], level + 1, remainder, original);
102
+ }
103
+ }
104
+
105
+ unsigned int search_and_remove_at_leaf(leaf_node leaf, unsigned long value)
106
+ {
107
+ unsigned int exist_flag = 0;
108
+ unsigned long target_bit;
109
+
110
+ target_bit = 1UL << value;
111
+
112
+ if ((leaf->data & target_bit)) {
113
+ leaf->data ^= target_bit;
114
+ exist_flag = 1;
115
+ }
116
+
117
+ return exist_flag;
118
+ }
data/ext/init.c ADDED
@@ -0,0 +1,167 @@
1
+ //************************************
2
+ // init.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //
12
+ // initialize
13
+ //
14
+ void init_root_node(root_node root)
15
+ {
16
+ unsigned int i;
17
+
18
+ for(i = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE; i++) {
19
+ root->index[i] = (void*)NULL;
20
+ }
21
+ root->size = 0;
22
+ root->children_size = 0;
23
+ }
24
+
25
+ void *init_branch_node()
26
+ {
27
+ unsigned int i;
28
+ branch_node branch;
29
+
30
+ if (!(branch = (branch_node)malloc(sizeof(struct _branch_node)))) {
31
+ rb_raise(rb_eStandardError, "memory is not enough");
32
+ }
33
+
34
+ for(i = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH; i++) {
35
+ branch->index[i] = (void*)NULL;
36
+ }
37
+
38
+ branch->children_size = 0;
39
+ branch->children_type = CT_BRANCH;
40
+
41
+ return (void*)branch;
42
+ }
43
+
44
+ void *init_leaf_node(unsigned long offset)
45
+ {
46
+ leaf_node leaf;
47
+
48
+ if(!(leaf = (leaf_node)malloc(sizeof(struct _leaf_node)))) {
49
+ rb_raise(rb_eStandardError, "memory is not enough");
50
+ }
51
+
52
+ leaf->offset = offset;
53
+ leaf->data = 0;
54
+
55
+ return (void*)leaf;
56
+ }
57
+
58
+ //
59
+ // initialize copy
60
+ //
61
+ void copy_root_node(root_node root, root_node orig)
62
+ {
63
+ unsigned int i, count;
64
+
65
+ root->children_size = orig->children_size;
66
+
67
+ for (i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE || count < orig->children_size; i++) {
68
+ if (orig->index[i]) {
69
+ root->index[i] = init_and_copy_brance_node(root, (branch_node)orig->index[i]);
70
+ count++;
71
+ }
72
+ }
73
+ }
74
+
75
+ void copy_branch_node(root_node root, branch_node branch, branch_node orig)
76
+ {
77
+ unsigned int i, count;
78
+
79
+ branch->children_type = orig->children_type;
80
+ branch->children_size = orig->children_size;
81
+
82
+ if (orig->children_type == CT_LEAF) {
83
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < orig->children_size; i++) {
84
+ if (orig->index[i]) {
85
+ branch->index[i] = init_and_copy_leaf_node(root, (leaf_node)orig->index[i]);
86
+ count++;
87
+ }
88
+ }
89
+ } else {
90
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < orig->children_size; i++) {
91
+ if (orig->index[i]) {
92
+ branch->index[i] = init_and_copy_brance_node(root, (branch_node)orig->index[i]);
93
+ count++;
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ void *init_and_copy_brance_node(root_node root, branch_node orig)
100
+ {
101
+ branch_node branch;
102
+
103
+ branch = (branch_node)init_branch_node();
104
+ copy_branch_node(root, branch, orig);
105
+
106
+ return (void*)branch;
107
+ }
108
+
109
+ void *init_and_copy_leaf_node(root_node root, leaf_node orig)
110
+ {
111
+ leaf_node leaf;
112
+
113
+ leaf = (leaf_node)init_leaf_node(orig->offset);
114
+ leaf->data = orig->data;
115
+ root->size += BIT_COUNT(leaf->data);
116
+
117
+ return (void*)leaf;
118
+ }
119
+
120
+ //
121
+ // memory free
122
+ //
123
+ void destroy_all(root_node root)
124
+ {
125
+ destroy_all_branches(root);
126
+ free(root);
127
+ }
128
+
129
+ void destroy_all_branches(root_node root)
130
+ {
131
+ unsigned int i, count;
132
+
133
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE || count < root->children_size; i++) {
134
+ if (root->index[i]) {
135
+ destroy_branch((branch_node)root->index[i]);
136
+ root->index[i] = (void*)NULL;
137
+ count++;
138
+ }
139
+ }
140
+
141
+ root->size = 0;
142
+ root->children_size = 0;
143
+ }
144
+
145
+ void destroy_branch(branch_node branch)
146
+ {
147
+ unsigned int i, count;
148
+
149
+ if (branch->children_type == CT_LEAF) {
150
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < branch->children_size; i++) {
151
+ if (branch->index[i]) {
152
+ free((leaf_node)branch->index[i]);
153
+ branch->index[i] = (void*)NULL;
154
+ count++;
155
+ }
156
+ }
157
+ } else {
158
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < branch->children_size; i++) {
159
+ if (branch->index[i]) {
160
+ destroy_branch((branch_node)branch->index[i]);
161
+ branch->index[i] = (void*)NULL;
162
+ count++;
163
+ }
164
+ }
165
+ }
166
+ free(branch);
167
+ }
data/ext/methods.c ADDED
@@ -0,0 +1,245 @@
1
+ //************************************
2
+ // method.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //-----------------------------------------------------------
12
+ // Ruby Methods
13
+ // ----------------------------------------------------------
14
+
15
+ /**
16
+ * allocate
17
+ **/
18
+ static VALUE t_allocate(VALUE klass)
19
+ {
20
+ VALUE obj;
21
+ root_node root;
22
+
23
+ obj = Data_Make_Struct(klass, struct _root_node, NULL, destroy_all, root);
24
+ init_root_node(root);
25
+
26
+ return obj;
27
+ }
28
+
29
+ /**
30
+ * initialize
31
+ **/
32
+ static VALUE t_initialize(int argc, VALUE *argv, VALUE self)
33
+ {
34
+ VALUE num, ary_element;
35
+ root_node root;
36
+ unsigned long i, len;
37
+
38
+ Data_Get_Struct(self, struct _root_node, root);
39
+
40
+ if (argc == 1 && TYPE(argv[0]) == T_ARRAY) {
41
+ len = RARRAY_LEN(argv[0]);
42
+ for(i = 0; i < len; i++) {
43
+ ary_element = rb_ary_entry(argv[0], i);
44
+ if ((TYPE(ary_element) == T_FIXNUM) && VALID_MIN_VALUE <= ary_element && VALID_MAX_VALUE >= ary_element) {
45
+ add_num(root, NUM2ULONG(ary_element));
46
+ }
47
+ }
48
+ }
49
+
50
+ return self;
51
+ }
52
+
53
+ /**
54
+ * initialize_copy
55
+ **/
56
+ static VALUE t_initialize_copy(VALUE self, VALUE orig)
57
+ {
58
+ root_node root, orig_set;
59
+
60
+ Data_Get_Struct(self, struct _root_node, root);
61
+ Data_Get_Struct(orig, struct _root_node, orig_set);
62
+ copy_root_node(root, orig_set);
63
+
64
+ return self;
65
+ }
66
+
67
+ /**
68
+ * add
69
+ **/
70
+ static VALUE t_add(VALUE self, VALUE value)
71
+ {
72
+ root_node root;
73
+
74
+ if (TYPE(value) != T_FIXNUM) return;
75
+ if (VALID_MIN_VALUE > value || VALID_MAX_VALUE < value) return;
76
+
77
+ Data_Get_Struct(self, struct _root_node, root);
78
+ add_num(root, NUM2ULONG(value));
79
+
80
+ return self;
81
+ }
82
+
83
+ /**
84
+ * delete
85
+ **/
86
+ static VALUE t_delete(VALUE self, VALUE value)
87
+ {
88
+ root_node root;
89
+
90
+ if (TYPE(value) != T_FIXNUM) return;
91
+ if (VALID_MIN_VALUE > value || VALID_MAX_VALUE < value) return;
92
+
93
+ Data_Get_Struct(self, struct _root_node, root);
94
+ delete_num(root, NUM2ULONG(value));
95
+
96
+ return self;
97
+ }
98
+
99
+ /**
100
+ * intersection
101
+ **/
102
+ static VALUE t_intersection(VALUE self, VALUE other)
103
+ {
104
+ VALUE obj;
105
+ root_node result_set, set0, set1;
106
+
107
+ obj = Data_Make_Struct(rb_cFigureSet, struct _root_node, NULL, destroy_all, result_set);
108
+ init_root_node(result_set);
109
+
110
+ Data_Get_Struct(self, struct _root_node, set0);
111
+ Data_Get_Struct(other, struct _root_node, set1);
112
+
113
+ intersection(result_set, set0, set1);
114
+
115
+ return obj;
116
+ }
117
+
118
+ /**
119
+ * union
120
+ **/
121
+ static VALUE t_union(VALUE self, VALUE other)
122
+ {
123
+ VALUE obj;
124
+ root_node result_set, set0, set1;
125
+
126
+ obj = Data_Make_Struct(rb_cFigureSet, struct _root_node, NULL, destroy_all, result_set);
127
+ init_root_node(result_set);
128
+
129
+ Data_Get_Struct(self, struct _root_node, set0);
130
+ Data_Get_Struct(other, struct _root_node, set1);
131
+
132
+ join(result_set, set0, set1);
133
+
134
+ return obj;
135
+ }
136
+
137
+ /**
138
+ * to_a
139
+ **/
140
+ static VALUE t_to_a(VALUE self)
141
+ {
142
+ root_node root;
143
+ VALUE array;
144
+
145
+ Data_Get_Struct(self, struct _root_node, root);
146
+ array = rb_ary_new2(root->size);
147
+
148
+ to_array(root, array);
149
+
150
+ return array;
151
+ }
152
+
153
+ /**
154
+ * sample
155
+ **/
156
+ static VALUE t_sample(int argc, VALUE *argv, VALUE self)
157
+ {
158
+ root_node root;
159
+ VALUE array;
160
+ unsigned long sample_count = 1UL;
161
+
162
+ Data_Get_Struct(self, struct _root_node, root);
163
+
164
+ if (argc == 1 && TYPE(argv[0]) == T_FIXNUM) {
165
+ sample_count = NUM2ULONG(argv[0]);
166
+ if (sample_count < 1UL || sample_count > root->size) sample_count = 1UL;
167
+ }
168
+
169
+ array = rb_ary_new2(sample_count);
170
+ if (sample_count == root->size) {
171
+ to_array(root, array);
172
+ } else {
173
+ sample(root, array, sample_count);
174
+ }
175
+
176
+ return array;
177
+ }
178
+
179
+ /**
180
+ * size
181
+ **/
182
+ static VALUE t_size(VALUE self)
183
+ {
184
+ root_node root;
185
+
186
+ Data_Get_Struct(self, struct _root_node, root);
187
+
188
+ return ULONG2NUM(root->size);
189
+ }
190
+
191
+ /**
192
+ * empty?
193
+ **/
194
+ static VALUE t_empty(VALUE self)
195
+ {
196
+ root_node root;
197
+
198
+ Data_Get_Struct(self, struct _root_node, root);
199
+
200
+ if (root->size == 0) {
201
+ return Qtrue;
202
+ } else {
203
+ return Qfalse;
204
+ }
205
+ }
206
+
207
+ /**
208
+ * cler
209
+ **/
210
+ static VALUE t_clear(VALUE self)
211
+ {
212
+ root_node root;
213
+
214
+ Data_Get_Struct(self, struct _root_node, root);
215
+
216
+ if (root->size) {
217
+ destroy_all_branches(root);
218
+ }
219
+
220
+ return self;
221
+ }
222
+
223
+
224
+ /**
225
+ * define class
226
+ **/
227
+ void Init_figure_set(void) {
228
+ rb_cFigureSet = rb_define_class("FigureSet", rb_cObject);
229
+ rb_define_alloc_func(rb_cFigureSet, t_allocate);
230
+ rb_define_private_method(rb_cFigureSet, "initialize", t_initialize, -1);
231
+ rb_define_method(rb_cFigureSet, "initialize_copy", t_initialize_copy, 1);
232
+ rb_define_method(rb_cFigureSet, "add", t_add, 1);
233
+ rb_define_method(rb_cFigureSet, "delete", t_delete, 1);
234
+ rb_define_method(rb_cFigureSet, "intersection", t_intersection, 1);
235
+ rb_define_method(rb_cFigureSet, "union", t_union, 1);
236
+ rb_define_method(rb_cFigureSet, "to_a", t_to_a, 0);
237
+ rb_define_method(rb_cFigureSet, "sample", t_sample, -1);
238
+ rb_define_method(rb_cFigureSet, "size", t_size, 0);
239
+ rb_define_method(rb_cFigureSet, "empty?", t_empty, 0);
240
+ rb_define_method(rb_cFigureSet, "clear", t_clear, 0);
241
+ rb_define_alias(rb_cFigureSet, "<<", "add");
242
+ rb_define_alias(rb_cFigureSet, "&", "intersection");
243
+ rb_define_alias(rb_cFigureSet, "|", "union");
244
+ rb_define_alias(rb_cFigureSet, "length", "size");
245
+ }
data/ext/or.c ADDED
@@ -0,0 +1,105 @@
1
+ //************************************
2
+ // or.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <ruby.h>
9
+ #include "figure_set.h"
10
+
11
+ //
12
+ // join
13
+ //
14
+ void join(root_node result_set, root_node set0, root_node set1)
15
+ {
16
+ unsigned int i;
17
+
18
+ if (set0->size == 0 && set1->size == 0) {
19
+ return;
20
+ } else if (set0->size == 0) {
21
+ copy_root_node(result_set, set1);
22
+ return;
23
+ } else if (set1->size == 0) {
24
+ copy_root_node(result_set, set0);
25
+ return;
26
+ }
27
+
28
+ for (i = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE; i++) {
29
+ if (set0->index[i] && set1->index[i]) {
30
+ result_set->index[i] = init_and_join_brance_node(result_set, (branch_node)set0->index[i], (branch_node)set1->index[i]);
31
+ result_set->children_size++;
32
+ } else if(set0->index[i]) {
33
+ result_set->index[i] = init_and_copy_brance_node(result_set, (branch_node)set0->index[i]);
34
+ result_set->children_size++;
35
+ } else if (set1->index[i]) {
36
+ result_set->index[i] = init_and_copy_brance_node(result_set, (branch_node)set1->index[i]);
37
+ result_set->children_size++;
38
+ }
39
+ }
40
+ }
41
+
42
+
43
+ void *init_and_join_brance_node(root_node result_set, branch_node set0, branch_node set1)
44
+ {
45
+ branch_node branch;
46
+
47
+ branch = (branch_node)init_branch_node();
48
+
49
+ if (set0->children_type == CT_LEAF) {
50
+ branch->children_type = CT_LEAF;
51
+ last_join_branch_node(result_set, branch, set0, set1);
52
+ } else {
53
+ middle_join_branch_node(result_set, branch, set0, set1);
54
+ }
55
+
56
+ return (void*)branch;
57
+ }
58
+
59
+ void middle_join_branch_node(root_node result_set, branch_node branch, branch_node set0, branch_node set1)
60
+ {
61
+ unsigned int i;
62
+
63
+ for (i = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH; i++) {
64
+ if (set0->index[i] && set1->index[i]) {
65
+ branch->index[i] = init_and_join_brance_node(result_set, (branch_node)set0->index[i], (branch_node)set1->index[i]);
66
+ branch->children_size++;
67
+ } else if (set0->index[i]) {
68
+ branch->index[i] = init_and_copy_brance_node(result_set, (branch_node)set0->index[i]);
69
+ branch->children_size++;
70
+ } else if (set1->index[i]) {
71
+ branch->index[i] = init_and_copy_brance_node(result_set, (branch_node)set1->index[i]);
72
+ branch->children_size++;
73
+ }
74
+ }
75
+ }
76
+
77
+ void last_join_branch_node(root_node result_set, branch_node branch, branch_node set0, branch_node set1)
78
+ {
79
+ unsigned int i;
80
+
81
+ for (i = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH; i++) {
82
+ if (set0->index[i] && set1->index[i]) {
83
+ branch->index[i] = init_and_join_leaf_node(result_set, (leaf_node)set0->index[i], (leaf_node)set1->index[i]);
84
+ branch->children_size++;
85
+ } else if (set0->index[i]) {
86
+ branch->index[i] = init_and_copy_leaf_node(result_set, (leaf_node)set0->index[i]);
87
+ branch->children_size++;
88
+ } else if (set1->index[i]) {
89
+ branch->index[i] = init_and_copy_leaf_node(result_set, (leaf_node)set1->index[i]);
90
+ branch->children_size++;
91
+ }
92
+ }
93
+ }
94
+
95
+ void *init_and_join_leaf_node(root_node result_set, leaf_node set0, leaf_node set1)
96
+ {
97
+ leaf_node leaf;
98
+
99
+ leaf = (leaf_node)init_leaf_node(set0->offset);
100
+
101
+ leaf->data = set0->data | set1->data;
102
+ result_set->size += BIT_COUNT(leaf->data);
103
+
104
+ return (void*)leaf;
105
+ }
data/ext/sample.c ADDED
@@ -0,0 +1,89 @@
1
+ //************************************
2
+ // sample.c
3
+ //************************************
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <time.h>
9
+ #include <ruby.h>
10
+ #include "figure_set.h"
11
+
12
+ //
13
+ // output Array object from sample set
14
+ //
15
+ void sample(root_node root, VALUE array, unsigned long sample_count)
16
+ {
17
+ unsigned int start_sample, sample_now, i, count, target_point;
18
+
19
+ srand((unsigned) time(NULL));
20
+
21
+ start_sample = RARRAY_LEN(array);
22
+
23
+ for(sample_now = start_sample; sample_now < sample_count; sample_now++) {
24
+ target_point = rand() % root->children_size;
25
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_ROOT_NODE || count < root->children_size; i++) {
26
+ if (root->index[i]) {
27
+ if (count == target_point) {
28
+ search_and_sample_array((branch_node)root->index[i], array);
29
+ }
30
+ count++;
31
+ }
32
+ }
33
+ }
34
+
35
+ if (RARRAY_LEN(array) < sample_count) {
36
+ sample(root, array, sample_count);
37
+ }
38
+
39
+ rb_funcall(array, rb_intern("uniq!"), 0);
40
+ if (RARRAY_LEN(array) < sample_count) {
41
+ sample(root, array, sample_count);
42
+ }
43
+ }
44
+
45
+ void search_and_sample_array(branch_node branch, VALUE array)
46
+ {
47
+ unsigned int i, count, target_point;
48
+
49
+ if (!branch->children_size) return;
50
+
51
+ target_point = rand() % branch->children_size;
52
+
53
+ for(i = 0, count = 0; i < MAX_CHILDREN_SIZE_OF_BRANCH || count < branch->children_size; i++) {
54
+ if (branch->index[i]) {
55
+ if (count == target_point) {
56
+ if (branch->children_type == CT_LEAF) {
57
+ search_and_sample_array_at_leaf((leaf_node)branch->index[i], array);
58
+ } else {
59
+ search_and_sample_array((branch_node)branch->index[i], array);
60
+ }
61
+ }
62
+ count++;
63
+ }
64
+ }
65
+ }
66
+
67
+ void search_and_sample_array_at_leaf(leaf_node leaf, VALUE array)
68
+ {
69
+ unsigned long i = 0, hit_count = 0;
70
+ unsigned long bit_count, target_point;
71
+ unsigned long x;
72
+
73
+ x = leaf->data;
74
+ bit_count = BIT_COUNT(leaf->data);
75
+ if (!bit_count) return;
76
+
77
+ target_point = rand() % bit_count;
78
+
79
+ while(x) {
80
+ if (x & 1UL) {
81
+ if (hit_count == target_point) {
82
+ rb_ary_push(array, ULONG2NUM(leaf->offset + i));
83
+ }
84
+ hit_count++;
85
+ }
86
+ x = x >> 1UL;
87
+ i++;
88
+ }
89
+ }
data/lib/figure_set.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'figure_set.so'
2
+
3
+ class FigureSet
4
+ VERSION = "0.0.1"
5
+
6
+ class << self
7
+ def version
8
+ VERSION
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: figure_set
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Tsukasa OISHI
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-11-26 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: newgem
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 25
30
+ segments:
31
+ - 1
32
+ - 2
33
+ - 3
34
+ version: 1.2.3
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: hoe
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 55
46
+ segments:
47
+ - 1
48
+ - 8
49
+ - 0
50
+ version: 1.8.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ description: FigureSet.
54
+ email:
55
+ - tsukasa.oishi@gmail.com
56
+ executables: []
57
+
58
+ extensions:
59
+ - ext/extconf.rb
60
+ extra_rdoc_files:
61
+ - History.txt
62
+ - Manifest.txt
63
+ - README.rdoc
64
+ files:
65
+ - History.txt
66
+ - Manifest.txt
67
+ - README.rdoc
68
+ - Rakefile
69
+ - lib/figure_set.rb
70
+ - ext/extconf.rb
71
+ - ext/figure_set.h
72
+ - ext/methods.c
73
+ - ext/init.c
74
+ - ext/index.c
75
+ - ext/and.c
76
+ - ext/or.c
77
+ - ext/array.c
78
+ - ext/sample.c
79
+ has_rdoc: true
80
+ homepage: http://www.kaeruspoon.net/
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options:
85
+ - --main
86
+ - README.rdoc
87
+ require_paths:
88
+ - lib
89
+ - ext
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ requirements: []
109
+
110
+ rubyforge_project: figure_set
111
+ rubygems_version: 1.6.2
112
+ signing_key:
113
+ specification_version: 2
114
+ summary: FigureSet.
115
+ test_files: []
116
+