figure_set 0.0.1

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/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
+