miniball_ruby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/lib/ruby/1.8/i686-linux
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/usr
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(prefix)/share/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(prefix)/lib/ruby1.8
19
+ sitedir = $(DESTDIR)/usr/local/lib/site_ruby
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(prefix)/share/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(DESTDIR)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(DESTDIR)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = gcc
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 -fPIC $(cflags)
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS = -D_FILE_OFFSET_BITS=64
50
+ CPPFLAGS = $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = $(CC) -shared
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby1.8
61
+ RUBY_SO_NAME = ruby1.8
62
+ arch = i686-linux
63
+ sitearch = i686-linux
64
+ ruby_version = 1.8
65
+ ruby = /usr/bin/ruby1.8
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix = /miniball_ruby
88
+ LOCAL_LIBS =
89
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -lrt -ldl -lcrypt -lm -lc
90
+ SRCS = util.c miniball_builder_dynamic_d.c point_dynamic_d.c miniball_dynamic_d.c miniball_ruby.c
91
+ OBJS = util.o miniball_builder_dynamic_d.o point_dynamic_d.o miniball_dynamic_d.o miniball_ruby.o
92
+ TARGET = miniball_ruby
93
+ DLLIB = $(TARGET).so
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS) Makefile
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ #TODO: Try to include the non-dynamic versions for 2 and 3 dimensions
4
+ #TODO: Switch to ffi? Also check out ffi-inliner
5
+ create_makefile 'miniball_ruby/miniball_ruby'
@@ -0,0 +1,188 @@
1
+ #include <stdlib.h>
2
+ #include "util.h"
3
+ #include "point_dynamic_d.h"
4
+ #include "miniball_builder_dynamic_d.h"
5
+
6
+ MiniballBuilder* MiniballBuilder_create(int dim) {
7
+ int size = sizeof(double) * (dim+1);
8
+ int innerSize = sizeof(double) * dim;
9
+
10
+ MiniballBuilder* mb = malloc(sizeof(MiniballBuilder));
11
+
12
+ mb->d = dim;
13
+
14
+ mb->q0 = malloc(size);
15
+ mb->z = malloc(size);
16
+ mb->f = malloc(size);
17
+ mb->sqr_r = malloc(size);
18
+
19
+ mb->v = malloc(size);
20
+ mb->a = malloc(size);
21
+ mb->c = malloc(size);
22
+
23
+ int i;
24
+ for(i = 0; i < dim + 1; ++i) {
25
+ mb->v[i] = malloc(innerSize);
26
+ mb->a[i] = malloc(innerSize);
27
+ mb->c[i] = malloc(innerSize);
28
+ }
29
+
30
+ MiniballBuilder_reset(mb);
31
+
32
+ return mb;
33
+ }
34
+
35
+ void MiniballBuilder_destroy(MiniballBuilder* mb) {
36
+ int i;
37
+ for(i = 0; i < mb->d + 1; ++i) {
38
+ free(mb->v[i]);
39
+ free(mb->a[i]);
40
+ free(mb->c[i]);
41
+ }
42
+
43
+ free(mb->v);
44
+ free(mb->a);
45
+ free(mb->c);
46
+
47
+ free(mb->q0);
48
+ free(mb->z);
49
+ free(mb->f);
50
+ free(mb->sqr_r);
51
+
52
+ free(mb);
53
+ }
54
+
55
+ const double* MiniballBuilder_center(MiniballBuilder* mb) {
56
+ return mb->current_c;
57
+ }
58
+
59
+ double MiniballBuilder_squared_radius(MiniballBuilder* mb) {
60
+ return mb->current_sqr_r;
61
+ }
62
+
63
+ int MiniballBuilder_size(MiniballBuilder* mb) {
64
+ return mb->m;
65
+ }
66
+
67
+ int MiniballBuilder_support_size(MiniballBuilder* mb) {
68
+ return mb->s;
69
+ }
70
+
71
+ double MiniballBuilder_excess(MiniballBuilder* mb, const Point* p) {
72
+ double e = -mb->current_sqr_r;
73
+ int i;
74
+ for(i = 0; i < mb->d; ++i) {
75
+ e += sqr(p->coord[i] - mb->current_c[i]);
76
+ }
77
+ return e;
78
+ }
79
+
80
+ void MiniballBuilder_reset(MiniballBuilder* mb) {
81
+ mb->m = mb->s = 0;
82
+ int i;
83
+ for(i = 0; i < mb->d; ++i) {
84
+ mb->c[0][i] = 0;
85
+ }
86
+ mb->current_c = mb->c[0];
87
+ mb->current_sqr_r = -1;
88
+ }
89
+
90
+ //TODO: Document
91
+ int MiniballBuilder_push(MiniballBuilder* mb, Point* p) {
92
+ int supPoint = mb->m;
93
+ int dim = mb->d;
94
+
95
+ int i, j;
96
+ double eps = 1e-32;
97
+ if(supPoint == 0) {
98
+ for(i = 0; i < dim; ++i) {
99
+ double c = p->coord[i];
100
+ mb->q0[i] = c;
101
+ mb->c[0][i] = c;
102
+ }
103
+ mb->sqr_r[0] = 0;
104
+ } else {
105
+ for(i = 0; i < dim; ++i) {
106
+ //Set v_m to Q_m
107
+ mb->v[supPoint][i] = p->coord[i] - mb->q0[i];
108
+ }
109
+
110
+ //Compute the a_{supPoint,i}, i < supPoint
111
+ for(i = 1; i < supPoint; ++i) {
112
+ double* a = mb->a[supPoint];
113
+ a[i] = 0;
114
+ for(j = 0; j < dim; ++j) {
115
+ a[i] += mb->v[i][j] * mb->v[supPoint][j];
116
+ }
117
+ a[i] *= (2 / mb->z[i]);
118
+ }
119
+
120
+ //Update v_m to Q_m - \bar{Q}_m
121
+ for(i = 1; i < supPoint; ++i) {
122
+ for(j = 0; j < dim; ++j) {
123
+ mb->v[supPoint][j] -= mb->a[supPoint][i] * mb->v[i][j];
124
+ }
125
+ }
126
+
127
+ //compute z_m
128
+ mb->z[supPoint] = 0;
129
+ for(j = 0; j < dim; ++j) {
130
+ mb->z[supPoint] += sqr(mb->v[supPoint][j]);
131
+ }
132
+ mb->z[supPoint] *= 2;
133
+
134
+ //Reject push if z_m too small
135
+ if(mb->z[supPoint] < eps * mb->current_sqr_r) {
136
+ return 0;
137
+ }
138
+
139
+ //Update c, sqr_c
140
+ double e = -mb->sqr_r[supPoint - 1];
141
+ for(i = 0; i < dim; ++i) {
142
+ e += sqr(p->coord[i] - mb->c[supPoint - 1][i]);
143
+ }
144
+ double f = e / mb->z[supPoint];
145
+ mb->f[supPoint] = f;
146
+
147
+ for(i = 0; i < dim; ++i) {
148
+ mb->c[supPoint][i] = mb->c[supPoint - 1][i] + f * mb->v[supPoint][i];
149
+ }
150
+ mb->sqr_r[supPoint] = mb->sqr_r[supPoint - 1] + e * f / 2;
151
+ }
152
+
153
+ mb->current_c = mb->c[supPoint];
154
+ mb->current_sqr_r = mb->sqr_r[supPoint];
155
+ mb->s = ++mb->m;
156
+ return 1;
157
+ }
158
+
159
+ void MiniballBuilder_pop(MiniballBuilder* mb) {
160
+ mb->m--;
161
+ }
162
+
163
+ double MiniballBuilder_slack(MiniballBuilder* mb) {
164
+ double* l = malloc(sizeof(double) * (mb->d + 1));
165
+ double min_l = 0;
166
+ l[0] = 1;
167
+
168
+ int i, k;
169
+ for(i = mb->s - 1; i > 0; --i) {
170
+ l[i] = mb->f[i];
171
+ for(k = mb->s - 1; k > i; --k) {
172
+ l[i] -= mb->a[k][i] * l[k];
173
+ }
174
+ if(l[i] < min_l) {
175
+ min_l = l[i];
176
+ }
177
+ l[0] -= l[i];
178
+ }
179
+
180
+ if(l[0] < min_l) {
181
+ min_l = l[0];
182
+ }
183
+
184
+ free(l);
185
+
186
+ return ((min_l < 0) ? -min_l : 0);
187
+ }
188
+
@@ -0,0 +1,43 @@
1
+ #ifndef __MINIBALL_B_DYNAMIC_D__
2
+ #define __MINIBALL_B_DYNAMIC_D__
3
+
4
+ #include "point_dynamic_d.h"
5
+
6
+ //Smallest enclosing ball with a set of n <= d+1 points *on the boundry*
7
+ typedef struct MiniballBuilder MiniballBuilder;
8
+
9
+ struct MiniballBuilder {
10
+ int d; //Dimension
11
+ int m, s; //Size and number of support points
12
+ double* q0;
13
+
14
+ double* z;
15
+ double* f;
16
+ double** v;
17
+ double** a;
18
+
19
+ double** c;
20
+ double* sqr_r;
21
+
22
+ double* current_c; //Refers to some c[j]
23
+ double current_sqr_r;
24
+ };
25
+
26
+ MiniballBuilder* MiniballBuilder_create(int dim);
27
+ void MiniballBuilder_destroy(MiniballBuilder* mb);
28
+
29
+ const double* MiniballBuilder_center(MiniballBuilder* mb);
30
+ double MiniballBuilder_squared_radius(MiniballBuilder* mb);
31
+
32
+ int MiniballBuilder_size(MiniballBuilder* mb);
33
+ int MiniballBuilder_support_size(MiniballBuilder* mb);
34
+ double MiniballBuilder_excess(MiniballBuilder* mb, const Point* p);
35
+
36
+ void MiniballBuilder_reset(MiniballBuilder* mb);
37
+
38
+ int MiniballBuilder_push(MiniballBuilder* mb, Point* p);
39
+ void MiniballBuilder_pop(MiniballBuilder* mb);
40
+
41
+ double MiniballBuilder_slack(MiniballBuilder* mb);
42
+
43
+ #endif
@@ -0,0 +1,207 @@
1
+ #include <stdlib.h>
2
+ #include "util.h"
3
+ #include "point_dynamic_d.h"
4
+ #include "miniball_builder_dynamic_d.h"
5
+ #include "miniball_dynamic_d.h"
6
+
7
+ Miniball* Miniball_create(int dim) {
8
+ Miniball* m = malloc(sizeof(Miniball));
9
+
10
+ m->d = dim;
11
+ m->B = MiniballBuilder_create(dim);
12
+
13
+ m->firstPoint = 0;
14
+ m->lastPoint = 0;
15
+ m->pointCount = 0;
16
+
17
+ return m;
18
+ }
19
+
20
+ void Miniball_destroy(Miniball* m) {
21
+ if(m->firstPoint != 0) {
22
+ Point* p = m->firstPoint;
23
+ while(p) {
24
+ Point* next = p->next;
25
+ Point_destroy(p);
26
+ p = next;
27
+ }
28
+ }
29
+ MiniballBuilder_destroy(m->B);
30
+ free(m);
31
+ }
32
+
33
+ void Miniball_check_in(Miniball* m, Point* p) {
34
+ if(m->firstPoint == 0) {
35
+ m->firstPoint = p;
36
+ m->lastPoint = p;
37
+ } else {
38
+ p->prev = m->lastPoint;
39
+ m->lastPoint->next = p;
40
+ m->lastPoint = p;
41
+ }
42
+ m->pointCount++;
43
+ }
44
+
45
+ void Miniball_build(Miniball* m) {
46
+ //The c++ version used std::list::end, which is _beyond_ the last element
47
+ //Tack a fake point on to the end of our list to emulate this, while avoiding
48
+ //any segfaults in post-run analysis that would be caused by using void.
49
+ Point* hack = Point_create(m->d);
50
+ Miniball_check_in(m, hack);
51
+
52
+ MiniballBuilder_reset(m->B);
53
+ m->support_end = m->firstPoint;
54
+ Miniball_pivot_mb(m, m->lastPoint);
55
+ }
56
+
57
+ void Miniball_move_to_front(Miniball* m, Point* p) {
58
+ if(m->support_end == p) {
59
+ m->support_end = p->next;
60
+ }
61
+
62
+ if(m->firstPoint == p) {
63
+ return;
64
+ }
65
+
66
+ if(p->prev) {
67
+ p->prev->next = p->next;
68
+ }
69
+ if(p->next) {
70
+ p->next->prev = p->prev;
71
+ }
72
+ m->firstPoint->prev = p;
73
+ p->next = m->firstPoint;
74
+ p->prev = 0;
75
+ m->firstPoint = p;
76
+ }
77
+
78
+ void Miniball_mtf_mb(Miniball* m, Point* i) {
79
+ m->support_end = m->firstPoint;
80
+ if(MiniballBuilder_size(m->B) == m->d + 1) {
81
+ return;
82
+ }
83
+
84
+ Point* k = m->firstPoint;
85
+ while(k != i) {
86
+ Point* next = k->next;
87
+ if(MiniballBuilder_excess(m->B, k) > 0) {
88
+ if(MiniballBuilder_push(m->B, k)) {
89
+ Miniball_mtf_mb(m, k);
90
+ MiniballBuilder_pop(m->B);
91
+ Miniball_move_to_front(m, k);
92
+ }
93
+ }
94
+ k = next;
95
+ }
96
+ }
97
+
98
+ void Miniball_pivot_mb(Miniball* m, Point* p) {
99
+ Point* t = m->firstPoint->next;
100
+ Miniball_mtf_mb(m, t);
101
+
102
+ double max_e, old_sqr_r = -1;
103
+
104
+ do {
105
+ Point* pivot;
106
+ max_e = Miniball_max_excess(m, t, p, &pivot);
107
+ if(max_e > 0) {
108
+ t = m->support_end;
109
+ if(t == pivot) {
110
+ t = t->next;
111
+ }
112
+ old_sqr_r = MiniballBuilder_squared_radius(m->B);
113
+ MiniballBuilder_push(m->B, pivot);
114
+ Miniball_mtf_mb(m, m->support_end);
115
+ MiniballBuilder_pop(m->B);
116
+ Miniball_move_to_front(m, pivot);
117
+ }
118
+ } while((max_e > 0) && (MiniballBuilder_squared_radius(m->B) > old_sqr_r));
119
+ }
120
+
121
+ double Miniball_max_excess(Miniball* m, Point* t, Point* i, Point** pivot) {
122
+ const double* c = MiniballBuilder_center(m->B);
123
+ const double sqr_r = MiniballBuilder_squared_radius(m->B);
124
+ double e, max_e = 0;
125
+
126
+ Point* k = t;
127
+ while(k != i) {
128
+ e = -sqr_r;
129
+ int j;
130
+ for(j = 0; j < m->d; ++j) {
131
+ e += sqr(k->coord[j] - c[j]);
132
+ }
133
+ if(e > max_e) {
134
+ max_e = e;
135
+ *pivot = k;
136
+ }
137
+ k = k->next;
138
+ }
139
+
140
+ return max_e;
141
+ }
142
+
143
+ Point* Miniball_center(Miniball* m) {
144
+ Point* p = Point_create(m->d);
145
+ Point_copy_dbl(p, MiniballBuilder_center(m->B));
146
+ return p;
147
+ }
148
+
149
+ double Miniball_squared_radius(Miniball* m) {
150
+ return MiniballBuilder_squared_radius(m->B);
151
+ }
152
+
153
+ int Miniball_nr_points(Miniball* m) {
154
+ return m->pointCount;
155
+ }
156
+
157
+ Point* Miniball_points_begin(Miniball* m) {
158
+ return m->firstPoint;
159
+ }
160
+
161
+ Point* Miniball_points_end(Miniball* m) {
162
+ return m->lastPoint;
163
+ }
164
+
165
+ int Miniball_nr_support_points(Miniball* m) {
166
+ return MiniballBuilder_support_size(m->B);
167
+ }
168
+
169
+ Point* Miniball_support_points_begin(Miniball* m) {
170
+ return m->firstPoint;
171
+ }
172
+
173
+ Point* Miniball_support_points_end(Miniball* m) {
174
+ return m->support_end;
175
+ }
176
+
177
+ double Miniball_accuracy(Miniball* m, double* slack) {
178
+ double e, max_e = 0;
179
+ int n_supp = 0;
180
+ Point* i = m->firstPoint;
181
+ while(i != m->support_end) {
182
+ e = MiniballBuilder_excess(m->B, i);
183
+ if(e < 0) {
184
+ e = -e;
185
+ }
186
+ if(e > max_e) {
187
+ max_e = e;
188
+ }
189
+ i = i->next;
190
+ }
191
+
192
+ while(i != m->lastPoint) {
193
+ e = MiniballBuilder_excess(m->B, i);
194
+ if(e > max_e) {
195
+ max_e = e;
196
+ }
197
+ i = i->next;
198
+ }
199
+
200
+ *slack = MiniballBuilder_slack(m->B);
201
+ return (max_e / Miniball_squared_radius(m));
202
+ }
203
+
204
+ int Miniball_is_valid(Miniball* m, double tolerance) {
205
+ double slack;
206
+ return ((Miniball_accuracy(m, &slack) < tolerance) && (slack == 0));
207
+ }
@@ -0,0 +1,43 @@
1
+ #ifndef __MINIBALL_DYNAMIC_D__
2
+ #define __MINIBALL_DYNAMIC_D__
3
+
4
+ #include "point_dynamic_d.h"
5
+ #include "miniball_builder_dynamic_d.h"
6
+
7
+ //Smallest enclosing ball of a set of n points in dimension d
8
+ typedef struct Miniball Miniball;
9
+
10
+ struct Miniball {
11
+ int d; //Dimension
12
+ MiniballBuilder* B; //The current ball
13
+
14
+ Point* firstPoint; //Start of internal point set
15
+ Point* lastPoint; //End of internal point set
16
+ int pointCount;
17
+
18
+ Point* support_end; //Past-the end iterator of support set
19
+ };
20
+
21
+ Miniball* Miniball_create(int dim);
22
+ void Miniball_destroy(Miniball* m);
23
+
24
+ void Miniball_check_in(Miniball* m, Point* p);
25
+ void Miniball_build(Miniball* m);
26
+ void Miniball_move_to_front(Miniball* m, Point* p);
27
+ void Miniball_mtf_mb(Miniball* m, Point* i);
28
+ void Miniball_pivot_mb(Miniball* m, Point* p);
29
+
30
+ double Miniball_max_excess(Miniball* m, Point* t, Point* i, Point** pivot);
31
+
32
+ Point* Miniball_center(Miniball* m);
33
+ double Miniball_squared_radius(Miniball* m);
34
+ int Miniball_nr_points(Miniball* m);
35
+ Point* Miniball_points_begin(Miniball* m);
36
+ Point* Miniball_points_end(Miniball* m);
37
+ int Miniball_nr_support_points(Miniball* m);
38
+ Point* Miniball_support_points_begin(Miniball* m);
39
+ Point* Miniball_support_points_end(Miniball* m);
40
+ double Miniball_accuracy(Miniball* m, double* slack);
41
+ int Miniball_is_valid(Miniball* m, double tolerance);
42
+
43
+ #endif
@@ -0,0 +1,169 @@
1
+ //TODO: Can push some more c ruby into this (and dependencies), like ALLOC
2
+
3
+ #include "ruby.h"
4
+ #include "util.h"
5
+ #include "point_dynamic_d.h"
6
+ #include "miniball_builder_dynamic_d.h"
7
+ #include "miniball_dynamic_d.h"
8
+
9
+ //
10
+ // Calculation result structue and accessors
11
+ //
12
+
13
+ VALUE MiniballResult;
14
+
15
+ typedef struct Result Result;
16
+
17
+ struct Result {
18
+ VALUE center;
19
+ VALUE radius_squared;
20
+ VALUE support_points;
21
+ VALUE accuracy;
22
+ VALUE slack;
23
+ };
24
+
25
+ Result* ConstructResult(int dim, double* center, double radius_squared) {
26
+ Result* r = malloc(sizeof(Result));
27
+
28
+ r->center = rb_ary_new2(dim);
29
+ int i;
30
+ for(i = 0; i < dim; ++i) {
31
+ rb_ary_store(r->center, i, rb_float_new(center[i]));
32
+ }
33
+
34
+ r->radius_squared = rb_float_new(radius_squared);
35
+
36
+ r->support_points = Qnil;
37
+ r->accuracy = Qnil;
38
+ r->slack = Qnil;
39
+
40
+ return r;
41
+ }
42
+
43
+ void MarkResult(Result* r) {
44
+ rb_gc_mark(r->center);
45
+ rb_gc_mark(r->radius_squared);
46
+ rb_gc_mark(r->support_points);
47
+ rb_gc_mark(r->accuracy);
48
+ rb_gc_mark(r->slack);
49
+ }
50
+
51
+ void DestroyResult(Result* r) {
52
+ free(r);
53
+ }
54
+
55
+ VALUE center(VALUE self) {
56
+ Result* r;
57
+ Data_Get_Struct(self, Result, r);
58
+ return r->center;
59
+ }
60
+
61
+ VALUE radius_squared(VALUE self) {
62
+ Result* r;
63
+ Data_Get_Struct(self, Result, r);
64
+ return r->radius_squared;
65
+ }
66
+
67
+ VALUE support_points(VALUE self) {
68
+ Result* r;
69
+ Data_Get_Struct(self, Result, r);
70
+ return r->support_points;
71
+ }
72
+
73
+ VALUE accuracy(VALUE self) {
74
+ Result* r;
75
+ Data_Get_Struct(self, Result, r);
76
+ return r->accuracy;
77
+ }
78
+
79
+ VALUE slack(VALUE self) {
80
+ Result* r;
81
+ Data_Get_Struct(self, Result, r);
82
+ return r->slack;
83
+ }
84
+
85
+
86
+
87
+ //
88
+ // Calculation methods
89
+ //
90
+
91
+ VALUE MiniballC;
92
+
93
+ static VALUE calc(VALUE self, VALUE points, VALUE with_analytics) {
94
+ Check_Type(points, T_ARRAY);
95
+ if(RARRAY_LEN(points) == 0) {
96
+ rb_raise(rb_eArgError, "Must have at least one point");
97
+ }
98
+
99
+ Check_Type(rb_ary_entry(points, 0), T_ARRAY);
100
+ int dim = RARRAY_LEN(rb_ary_entry(points, 0));
101
+
102
+ Miniball* m = Miniball_create(dim);
103
+
104
+ int i, j;
105
+ int len = RARRAY_LEN(points);
106
+ for(i = 0; i < len; ++i) {
107
+ VALUE point = rb_ary_entry(points, i);
108
+ Check_Type(point, T_ARRAY);
109
+ if(RARRAY_LEN(point) != dim) {
110
+ rb_raise(rb_eArgError, "Point dimensions must be consistent");
111
+ }
112
+
113
+ Point* p = Point_create(dim);
114
+ for(j = 0; j < dim; ++j) {
115
+ p->coord[j] = NUM2DBL(rb_ary_entry(point, j));
116
+ }
117
+ Miniball_check_in(m, p);
118
+ }
119
+
120
+ Miniball_build(m);
121
+
122
+ Point* center = Miniball_center(m);
123
+ double radius_squared = Miniball_squared_radius(m);
124
+ //TODO: Support points
125
+
126
+ Result* r = ConstructResult(dim, center->coord, radius_squared);
127
+
128
+ int support_point_count = Miniball_nr_support_points(m);
129
+ r->support_points = rb_ary_new2(support_point_count);
130
+
131
+ Point* support_point = Miniball_support_points_begin(m);
132
+ for(i = 0; i < support_point_count; i++, support_point = support_point->next) {
133
+ VALUE point = rb_ary_new2(dim);
134
+ for(j = 0; j < dim; ++j) {
135
+ rb_ary_store(point, j, rb_float_new(support_point->coord[j]));
136
+ }
137
+ rb_ary_store(r->support_points, i, point);
138
+ }
139
+
140
+ if(with_analytics) {
141
+ double slack;
142
+ r->accuracy = rb_float_new(Miniball_accuracy(m, &slack));
143
+ r->slack = slack;
144
+ }
145
+
146
+ VALUE result = Data_Wrap_Struct(MiniballResult, MarkResult, DestroyResult, r);
147
+
148
+ Miniball_destroy(m);
149
+ return result;
150
+ }
151
+
152
+
153
+
154
+ //
155
+ // Ruby init
156
+ //
157
+
158
+ void Init_miniball_ruby() {
159
+ MiniballC = rb_define_module("MiniballC");
160
+ rb_define_method(MiniballC, "calc", calc, 2);
161
+
162
+ MiniballResult = rb_define_class("MiniballResult", rb_cObject);
163
+ rb_define_method(MiniballResult, "center", center, 0);
164
+ rb_define_method(MiniballResult, "radius_squared", radius_squared, 0);
165
+ rb_define_method(MiniballResult, "support_points", support_points, 0);
166
+ rb_define_method(MiniballResult, "accuracy", accuracy, 0);
167
+ rb_define_method(MiniballResult, "slack", slack, 0);
168
+ }
169
+
Binary file
Binary file
@@ -0,0 +1,47 @@
1
+ #include <stdlib.h>
2
+ #include "point_dynamic_d.h"
3
+
4
+ Point* Point_create(int dim) {
5
+ Point* p = malloc(sizeof(Point));
6
+
7
+ p->d = dim;
8
+ p->coord = malloc(sizeof(double) * dim);
9
+
10
+ p->prev = 0;
11
+ p->next = 0;
12
+
13
+ return p;
14
+ }
15
+
16
+ void Point_destroy(Point* p) {
17
+ free(p->coord);
18
+ free(p);
19
+ }
20
+
21
+ void Point_copy_dbl(Point* dest, const double* source) {
22
+ int sourceDim = sizeof(source) / sizeof(double);
23
+ //assert(dest->d == sourceDim);
24
+ int i;
25
+ for(i = 0; i < dest->d; ++i) {
26
+ dest->coord[i] = source[i];
27
+ }
28
+ }
29
+
30
+ void Point_copy(Point* dest, const Point* source) {
31
+ int i;
32
+ if(dest->d != source->d) {
33
+ free(dest->coord);
34
+ dest->coord = malloc(sizeof(double) * source->d);
35
+ dest->d = source->d;
36
+ }
37
+
38
+ Point_copy_dbl(dest, source->coord);
39
+ }
40
+
41
+ double* Point_begin(Point* p) {
42
+ return p->coord;
43
+ }
44
+
45
+ double* Point_end(Point* p) {
46
+ return p->coord + p->d;
47
+ }
@@ -0,0 +1,24 @@
1
+ #ifndef __POINT__
2
+ #define __POINT__
3
+
4
+ typedef struct Point Point;
5
+
6
+ struct Point {
7
+ int d;
8
+ double* coord;
9
+
10
+ //Points can be used as doubly-linked lists (must free manually)
11
+ Point* prev;
12
+ Point* next;
13
+ };
14
+
15
+ Point* Point_create(int dim);
16
+ void Point_destroy(Point* p);
17
+
18
+ void Point_copy_dbl(Point* dest, const double* source);
19
+ void Point_copy(Point* dest, const Point* source);
20
+
21
+ double* Point_begin(Point* p);
22
+ double* Point_end(Point* p);
23
+
24
+ #endif
Binary file
@@ -0,0 +1,6 @@
1
+ #include "util.h"
2
+
3
+ inline double sqr(double r) {
4
+ return r * r;
5
+ }
6
+
@@ -0,0 +1,7 @@
1
+ #ifndef __MINIBALL_UTIL__
2
+ #define __MINIBALL_UTIL__
3
+
4
+ inline double sqr(double r);
5
+
6
+ #endif
7
+
Binary file
data/lib/miniball.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path('../miniball_ruby/miniball', __FILE__)
@@ -0,0 +1,48 @@
1
+ require 'miniball_ruby/miniball_ruby'
2
+
3
+ class Miniball
4
+ include MiniballC
5
+
6
+ def initialize(points)
7
+ @result = nil
8
+ @points = points
9
+ end
10
+
11
+ def calculate(with_analysis = false)
12
+ @result ||= calc(@points, with_analysis || false)
13
+ end
14
+
15
+ def center
16
+ calculate.center
17
+ end
18
+
19
+ def radius
20
+ @radius ||= radius_squared ** 0.5
21
+ end
22
+
23
+ def radius_squared
24
+ calculate.radius_squared
25
+ end
26
+
27
+ def support_points
28
+ calculate.support_points
29
+ end
30
+
31
+ #Must calculate with analytics on to get accuracy or slack
32
+
33
+ def accuracy
34
+ unless @accuracy
35
+ a = calculate.accuracy
36
+ @accuracy = a.nan? ? 0.0 : a
37
+ end
38
+ @accuracy
39
+ end
40
+
41
+ def slack
42
+ unless @slack
43
+ s = calculate.slack
44
+ @slack = (s == false ? 0.0 : slack)
45
+ end
46
+ @slack
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ class Miniball
2
+ VERSION = '0.0.2'
3
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: miniball_ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Mike Marion
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-27 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: yajl-ruby
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ description: |-
35
+ This gem finds minimum bounding spheres of a set of points.
36
+ It is a port of Bernd Gaertner's C++ miniball library.
37
+ email: mike.marion@gmail.com
38
+ executables: []
39
+
40
+ extensions:
41
+ - ext/miniball_ruby/extconf.rb
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - lib/miniball_ruby/miniball.rb
46
+ - lib/miniball_ruby/version.rb
47
+ - lib/miniball.rb
48
+ - ext/miniball_ruby/miniball_builder_dynamic_d.h
49
+ - ext/miniball_ruby/point_dynamic_d.o
50
+ - ext/miniball_ruby/util.c
51
+ - ext/miniball_ruby/miniball_builder_dynamic_d.c
52
+ - ext/miniball_ruby/extconf.rb
53
+ - ext/miniball_ruby/miniball_dynamic_d.o
54
+ - ext/miniball_ruby/miniball_ruby.o
55
+ - ext/miniball_ruby/point_dynamic_d.c
56
+ - ext/miniball_ruby/util.h
57
+ - ext/miniball_ruby/miniball_ruby.so
58
+ - ext/miniball_ruby/miniball_dynamic_d.c
59
+ - ext/miniball_ruby/miniball_builder_dynamic_d.o
60
+ - ext/miniball_ruby/miniball_ruby.c
61
+ - ext/miniball_ruby/Makefile
62
+ - ext/miniball_ruby/util.o
63
+ - ext/miniball_ruby/point_dynamic_d.h
64
+ - ext/miniball_ruby/miniball_dynamic_d.h
65
+ homepage: https://github.com/marionm/miniball_ruby
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project:
94
+ rubygems_version: 1.8.11
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Ruby/C implementation of miniball
98
+ test_files: []
99
+