commit 0986303c82c50be80b1dcf3ecb2d11ec0598dff1
parent 4f006c77769ed7a7c2a2a771192ca1a1e44abe90
Author: sin <sin@2f30.org>
Date: Wed, 10 Jun 2015 17:35:22 +0100
Switch to vector based representation for points
Diffstat:
4 files changed, 78 insertions(+), 15 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,7 +6,7 @@ MANPREFIX = $(PREFIX)/man
CPPFLAGS = -I/usr/local/include
CFLAGS = -Wall -O3
LDFLAGS = -L/usr/local/lib -lpng
-OBJ = colors.o png.o
+OBJ = colors.o png.o vector.o
BIN = colors
all: $(BIN)
@@ -14,8 +14,9 @@ all: $(BIN)
$(BIN): $(OBJ)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(OBJ) $(LDFLAGS)
-colors.o: arg.h colors.h queue.h
-png.o: arg.h colors.h queue.h
+colors.o: arg.h colors.h queue.h vector.h
+png.o: colors.h
+vector.o: vector.h
install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin
diff --git a/colors.c b/colors.c
@@ -9,6 +9,7 @@
#include "arg.h"
#include "colors.h"
#include "queue.h"
+#include "vector.h"
#define LEN(x) (sizeof (x) / sizeof *(x))
@@ -25,10 +26,11 @@ struct cluster {
};
char *argv0;
+
struct cluster *clusters;
size_t nclusters = 8;
-TAILQ_HEAD(points, point) points;
-size_t npoints;
+struct vector points;
+
int eflag;
int rflag;
int hflag;
@@ -159,9 +161,7 @@ initcluster_pixel(struct cluster *c, int i)
TAILQ_INIT(&c->members);
c->nmembers = 0;
- TAILQ_FOREACH(p, &points, e)
- if (i-- == 0)
- break;
+ p = vector_get(&points, i);
c->center = *p;
}
@@ -253,8 +253,8 @@ hasmember(struct cluster *c, struct point *p)
void
process(void)
{
- struct point *p, *tmp;
- int *dists, mind, mini, i, done = 0;
+ struct point *p;
+ int *dists, mind, mini, i, j, done = 0;
dists = malloc(nclusters * sizeof(*dists));
if (!dists)
@@ -262,7 +262,8 @@ process(void)
while (!done) {
done = 1;
- TAILQ_FOREACH_SAFE(p, &points, e, tmp) {
+ for (j = 0; j < vector_size(&points); j++) {
+ p = vector_get(&points, j);
for (i = 0; i < nclusters; i++)
dists[i] = distance(p, &clusters[i].center);
@@ -305,8 +306,7 @@ fillpoints(int r, int g, int b)
p->y = g;
p->z = b;
p->c = NULL;
- TAILQ_INSERT_TAIL(&points, p, e);
- npoints++;
+ vector_add(&points, p);
}
void
@@ -365,7 +365,7 @@ main(int argc, char *argv[])
if (argc != 1)
usage();
- TAILQ_INIT(&points);
+ vector_init(&points);
parseimg(argv[0], fillpoints);
if (mflag)
@@ -374,7 +374,7 @@ main(int argc, char *argv[])
srand(time(NULL));
if (pflag) {
initcluster = initcluster_pixel;
- initspace = npoints;
+ initspace = vector_size(&points);
}
if (hflag) {
initcluster = initcluster_hue;
diff --git a/vector.c b/vector.c
@@ -0,0 +1,48 @@
+#include <err.h>
+#include <stdlib.h>
+
+#include "vector.h"
+
+static void
+grow(struct vector *v)
+{
+ if (v->s >= v->c) {
+ v->c = !v->c ? 1 : v->c * 2;
+ v->d = realloc(v->d, sizeof(*v->d) * v->c);
+ if (!v->d)
+ err(1, "realloc");
+ }
+}
+
+void
+vector_init(struct vector *v)
+{
+ v->s = 0;
+ v->c = 0;
+ v->d = NULL;
+}
+
+void
+vector_free(struct vector *v)
+{
+ free(v->d);
+}
+
+void
+vector_add(struct vector *v, void *data)
+{
+ grow(v);
+ v->d[v->s++].raw = data;
+}
+
+void *
+vector_get(struct vector *v, size_t i)
+{
+ return v->d[i].raw;
+}
+
+size_t
+vector_size(struct vector *v)
+{
+ return v->s;
+}
diff --git a/vector.h b/vector.h
@@ -0,0 +1,14 @@
+struct vector_data {
+ void *raw;
+};
+
+struct vector {
+ struct vector_data *d;
+ size_t c;
+ size_t s;
+};
+
+void vector_init(struct vector *);
+void vector_add(struct vector *, void *);
+void *vector_get(struct vector *, size_t);
+size_t vector_size(struct vector *);