miniball_ruby 0.0.2

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.
@@ -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
+