diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ann.c | 64 | ||||
-rw-r--r-- | src/ann.h | 15 | ||||
-rw-r--r-- | src/ann_som.c | 721 | ||||
-rw-r--r-- | src/makefile.irix | 20 | ||||
-rw-r--r-- | src/makefile.linux | 76 |
5 files changed, 896 insertions, 0 deletions
diff --git a/src/ann.c b/src/ann.c new file mode 100644 index 0000000..8b0cb27 --- /dev/null +++ b/src/ann.c @@ -0,0 +1,64 @@ +/* ...this is an externals for comouting Aritficial Neural Networks... + thikn aboiut this + + 0201:forum::für::umläute:2001 +*/ + +#include "ann.h" + +typedef struct ann +{ + t_object t_ob; +} t_ann; + +t_class *ann_class; + +/* do a little help thing */ + +static void ann_help(void) +{ + post("\n\n...this is the ann external "VERSION"..\n"); + post("self-organized maps" + "\n\tann_som" + ""); + post("\n(l) forum::für::umläute 2001\n" + "this software is under the GnuGPL that is provided with these files"); +} + +void *ann_new(void) +{ + t_ann *x = (t_ann *)pd_new(ann_class); + return (void *)x; +} + +void ann_som_setup(); + +/* + waiting to be released in near future: + ANN_SOM : self organized maps + ANN_PERCEPTRON : perceptrons + ANN_MLP : multilayer perceptrons + + waiting to be realeased sometimes + ANN_RBF : radial basis functions +*/ + + + +void ann_setup(void) +{ + ann_som_setup(); + + + /* ************************************** */ + + post("\n\t................................"); + post("\t...artificial neural networks..."); + post("\t..........version "VERSION".........."); + post("\t....forum::für::umläute 2001...."); + post("\t....send me a 'help' message...."); + post("\t................................\n"); + + ann_class = class_new(gensym("ann"), ann_new, 0, sizeof(t_ann), 0, 0); + class_addmethod(ann_class, ann_help, gensym("help"), 0); +} diff --git a/src/ann.h b/src/ann.h new file mode 100644 index 0000000..48452d8 --- /dev/null +++ b/src/ann.h @@ -0,0 +1,15 @@ +/* ********************************************** */ +/* the ANN external */ +/* ********************************************** */ +/* forum::für::umläute */ +/* ********************************************** */ + +#ifndef INCLUDE_ANN_H__ +#define INCLUDE_ANN_H__ + +#include "m_pd.h" + +/* to beautify the logo make sure to make the VERSION-info 4 chars long */ +#define VERSION "0.1." + +#endif diff --git a/src/ann_som.c b/src/ann_som.c new file mode 100644 index 0000000..3247e39 --- /dev/null +++ b/src/ann_som.c @@ -0,0 +1,721 @@ +/* ann_som : + part of the ARTIFICIAL NEURAL NETWORK external for PURE DATA + SELF-ORGANIZED MAP : instar learning-rule + + (l) 0201:forum::für::umläute:2001 + this software is licensed under the GNU General Public License +*/ + +#include "ann.h" +#include <math.h> +#ifdef NT +#define sqrtf sqrt +#endif + +#if 1 +#include <stdio.h> +#include <fcntl.h> +#include <string.h> +#ifdef linux +#include <unistd.h> +#endif +#ifdef NT +#include <io.h> +#endif +#endif + +/* ****************************************************************************** */ +/* som : save and load messages... */ + +#define INSTAR 1 +#define OUTSTAR 2 +#define KOHONEN 0 + +/* learning-rule + INSTAR : instar learning-rule +*/ + +#define TRAIN 0 +#define TEST 1 + + +typedef struct _som { + t_object x_obj; + t_outlet *left, *right; + + int rule; /* INSTAR, OUTSTAR, KOHONEN */ + int mode; /* TRAIN, TEST */ + + t_symbol *filename; + int defaultfilename; /* TRUE if filename is still "default.som" */ + + int num_neurX, num_neurY; /* for 2dim-fields */ + int num_neurons; /* num_neurX * num_neurY */ + int num_sensors; + + t_float **weights; /* the neural network (pointer to neuron (neuron is a pointer to an array of weights)) */ + t_float **dist; /* squaredistances between neurons (for neighbourhood) (pointer to neuron (is a pointer to an array of distances))*/ + + t_float *workingspace; /* a for comparing data*/ + + double lr, lr_factor, lr_bias; /* learning rate: lr(n)=(lr(n-1)*lr_factor; LR=lr(n)+lr_bias */ + double nb, nb_factor, nb_bias; /* neighbourhood */ + + /* something for reading/writing to files */ + t_canvas *x_canvas; + t_symbol *x_dir; + +} t_som; + +static t_class *som_class; + +/* ----------------- private functions -------------------- */ + +static void som_killsom(t_som *x) +{ + /* kill the weights-field */ + int i=x->num_neurons; + + while (i--) { + freebytes(x->weights[i], sizeof(x->weights[i])); + x->weights[i]=0; + } + freebytes(x->weights, sizeof(x->weights)); + x->weights = 0; + + /* kill the dist-field */ + i=x->num_neurons; + + while (i--) { + freebytes(x->dist[i], sizeof(x->dist[i])); + x->dist[i]=0; + } + freebytes(x->dist, sizeof(x->dist)); + x->dist = 0; + + /* kill the working-space */ + freebytes(x->workingspace, sizeof(x->workingspace)); + x->workingspace = 0; +} + +static void som_makedist(t_som *x) +{ + int i, j; + + x->dist = (t_float **)getbytes(x->num_neurons * sizeof(t_float *)); + + for (i=0; i<x->num_neurons; i++) { + int x1 = (i%x->num_neurX), y1 = (i/x->num_neurX); + x->dist[i]=(t_float *)getbytes(x->num_neurons * sizeof(t_float)); + + for (j=0; j<x->num_neurons; j++) { + int x2 = (j%x->num_neurX), y2 = (j/x->num_neurX); + x->dist[i][j] = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); + } + } +} + +static int som_whosthewinner(t_som *x, t_float *senses) +{ + t_float min_dist = 0; + int min_n = x->num_neurons-1; + t_float *weight = x->weights[min_n]; + int n = x->num_sensors; + + while (n--) { + t_float f = senses[n] - weight[n]; + min_dist += f*f; + } + + n=x->num_neurons-1; + while (n--) { + int s = x->num_sensors; + + t_float dist = 0; + weight = x->weights[n]; + + while (s--) { + t_float f; + f = senses[s] - weight[s]; + dist += f*f; + } + if (dist<min_dist) { + min_dist = dist; + min_n = n; + } + } + + return min_n; +} + +static void som_createnewsom(t_som *x, int sens, int nx, int ny) +{ /* create a new SOM */ + int i, j; + + /* clean up the old SOM */ + som_killsom(x); + + + /* make new SOM */ + x->num_neurons = nx * ny; + x->num_neurX = nx; + x->num_neurY = ny; + x->num_sensors = sens; + + x->weights = (t_float **)getbytes(x->num_neurons * sizeof(t_float *)); + for (i=0; i<x->num_neurons; i++) { + x->weights[i]=(t_float *)getbytes(x->num_sensors * sizeof(t_float)); + + for (j=0; j<x->num_sensors; j++) x->weights[i][j] = 0; + } + + /* make new dist */ + som_makedist(x); + + /* make new workingspace */ + x->workingspace = (t_float *)getbytes(x->num_sensors * sizeof(t_float)); + for (i=0; i<x->num_sensors; i++) x->workingspace[i]=0.f; +} + +/* ----------------- public functions ---------------------- */ + +static void som_list(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* present the data */ + int i = x->num_sensors; + // t_float *data = (t_float *)getbytes(sizeof(t_float) * i); + t_float *data = x->workingspace; + t_float *dummy = data; + int winner; + + t_float learningrate = x->lr+x->lr_bias, neighbourhood = x->nb+x->nb_bias; + + /* first: extract the data */ + /* check if there is enough input data; fill up with zeros if not; if there's plenty, maybe forget about the rest */ + if ((i = x->num_sensors - argc) > 0) { + dummy = data + argc; + while (i--) *dummy++ = 0; + i = x->num_sensors; + } else i = x->num_sensors; + dummy = data; + /* really get the data */ + while (i--) *dummy++ = atom_getfloat(argv++); + + /* second: get the winning neuron */ + winner = som_whosthewinner(x, data); + + if (x->mode == TRAIN) { + /* third: learn something */ + /* update all the neurons that are within the neighbourhood */ + i=x->num_neurons; + switch (x->rule) { + case OUTSTAR: + while (i--) { + t_float dist = x->dist[winner][i]; + if (neighbourhood > dist) { + t_float factor = 1 - dist/neighbourhood; + t_float *weight=x->weights[i]; + int s = x->num_sensors; + + while (s--) weight[s] += learningrate*data[s]*(factor-weight[s]); + } + } + break; + case INSTAR: + while (i--) { + t_float dist = x->dist[winner][i]; + if (neighbourhood > dist) { + t_float factor = learningrate * (1 - dist/neighbourhood); + t_float *weight=x->weights[i]; + int s = x->num_sensors; + + while (s--) weight[s] += (data[s]-weight[s])*factor; + } + } + break; + default: + /* KOHONEN rule */ + while (i--) { + t_float dist = x->dist[winner][i]; + if (neighbourhood > dist) { + t_float *weight=x->weights[i]; + int s = x->num_sensors; + + while (s--) weight[s] += (data[s]-weight[s])*learningrate; + } + } + } + + /* update learning-rate and neighbourhood */ + x->lr *= x->lr_factor; + x->nb *= x->nb_factor; + } + + /* finally: do the output thing */ + /* do the output thing */ + outlet_float(x->x_obj.ob_outlet, winner); + + // freebytes(data, sizeof(t_float)*x->num_sensors); +} + +static void som_bang(t_som *x) +{ /* re-trigger the last output */ + error("som_bang: nothing to do"); +} + +static void som_init(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* initialize the neuron-weights */ + int i, j; + t_float f; + + switch (argc) { + case 0: + case 1: + f = (argc)?atom_getfloat(argv):0; + for (i=0; i<x->num_neurons; i++) + for (j=0; j<x->num_sensors; j++) + x->weights[i][j]=f; + break; + default: + if (argc == x->num_sensors) { + for (i=0; i<x->num_neurons; i++) + for (j=0; j<x->num_sensors; j++) + x->weights[i][j]=atom_getfloat(&argv[j]); + } else + error("som_init: you should pass a list of expected mean-values for each sensor to the SOM"); + } +} + + +static void som_makenewsom(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* create a new SOM */ + int sens, nx, ny; + + + /* check whether there is sufficient data to create a new SOM */ + if ((argc != 2) && (argc !=3)) { + error("som_new: wrong number of arguments (only 2 or 3 parameters are allowed)"); + return; + } + + /* 3 arguments : #sensors #neurX #neurY :: 2D-field of neurons with neurX * neurY items + 2 arguments : #sensors #neurXY :: 2D-field of neurons with neurXY* neurXY items + + to create more-dimensional fields, we now have to manually adjust the SOM-file (change the distances...) + LATER, we might do a function "ann_makedist" + */ + + sens = atom_getfloat(argv); + if (sens <= 0) { + error("some_new: number of sensors must be >= 1"); + return; + } + + if (argc==3) { + nx = atom_getint(argv+1); + ny = atom_getint(argv+2); + if ((nx<=0) || (ny<=0)) { + error("some_new: number of neurons must be >= 1"); + return; + } + } else { + nx = atom_getint(argv+1); + if (nx<=0) { + error("some_new: number of neurons must be >= 1"); + return; + } + ny = nx; + } + + som_createnewsom(x, sens, nx, ny); +} + +static void som_train(t_som *x) +{ /* set the mode to TRAIN */ + x->mode = TRAIN; +} +static void som_test(t_som *x) +{ /* set the mode to TEST */ + x->mode = TEST; +} + +static void som_rule(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* set the learning rule */ + int rule=-1; + + if (argc>1) { + error("som_rule: only 1 argument may be specified"); + return; + } + if (argc == 0) { + post("som_rule: you are currently training with the %s rule", (x->rule==INSTAR)?"INSTAR":(x->rule==OUTSTAR)?"OUTSTAR":"KOHONEN"); + return; + } + + if (argv->a_type==A_FLOAT) rule=atom_getint(argv); + else if (argv->a_type==A_SYMBOL) { + char *name=atom_getsymbol(argv)->s_name; + if (!strcmp(name, "instar") && !strcmp(name, "INSTAR")) rule=INSTAR; + else if (!strcmp(name, "outstar") && !strcmp(name, "OUTSTAR")) rule=OUTSTAR; + else if (!strcmp(name, "kohonen") && !strcmp(name, "KOHONEN")) rule=KOHONEN; + } + + switch (rule) { + case KOHONEN: + case INSTAR: + case OUTSTAR: + x->rule=rule; + break; + default: + error("som_rule: you specified an invalid rule !"); + } +} + + +static void som_learn(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* set a new LEARNINGRATE */ + switch (argc) { + case 3: + x->lr_bias = atom_getfloat(&argv[2]); + case 2: + x->lr_factor = atom_getfloat(&argv[1]); + case 1: + x->lr = atom_getfloat(&argv[0]); + break; + default: + error("som_learn: you should pass up to 4 learning-rate parameters"); + } +} +static void som_neighbour(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* set a new NEIGHBOURHOOD */ + switch (argc) { + case 3: + x->nb_bias = atom_getfloat(&argv[2]); + case 2: + x->nb_factor = atom_getfloat(&argv[1]); + case 1: + x->nb = atom_getfloat(&argv[0]); + break; + default: + error("som_neighbour: you should pass up to 4 neighbourhood parameters"); + } +} + +static void som_read(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* read a som-file */ + + int fd; + char filnam[MAXPDSTRING]; + char buf[MAXPDSTRING], *bufptr; + + int neuronsX, neuronsY, sensors, rule=0; + double lr[3], nb[3]; + t_float dummy; + char *text=0; + int i, j; + t_float *fp; + + FILE *f=0; + + text = (char *)getbytes(MAXPDSTRING*sizeof(char)); + + if (argc>0) { + x->filename = atom_gensym(argv); + x->defaultfilename = 0; + } + if (x->defaultfilename) error("som_read: reading from default file \"%s\"", x->filename->s_name); + + if ((fd = open_via_path(canvas_getdir(x->x_canvas)->s_name, + x->filename->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0) { + error("%s: can't open", x->filename->s_name); + return; + } + else + close (fd); + + /* open */ + sys_bashfilename(x->filename->s_name, filnam); + dummy = 0; + + while (f == 0) { + if (!(f = fopen(filnam, "r"))) { + error("msgfile_read: unable to open %s", filnam); + return; + } + + /* read */ + + /* read header */ + if ( (dummy=fscanf(f,"SOM:\n%d",&sensors)) != 1) { + error("som_read: error reading file\n"); + break; + } + if ( (dummy=fscanf(f,"%d",&neuronsX)) != 1) { + error("som_read: error reading file\n"); + break; + } + if ( (dummy=fscanf(f,"%d",&neuronsY)) != 1) { + error("som_read: error reading file\n"); + break; + } + fscanf(f,"%s",text); + if (!strcmp("INSTAR", text)) rule = INSTAR; + else if (!strcmp("OUTSTAR", text)) rule = OUTSTAR; + else if (!strcmp("KOHONEN", text)) rule = KOHONEN; + + for (i=0; i<3; i++) + if ( (fscanf(f,"%lf",&lr[i])) != 1) { + error("som_read: error reading file\n"); + break; + } + for (i=0; i<3; i++) + if ( (fscanf(f,"%lf",&nb[i])) != 1) { + error("som_read: error reading file\n"); + break; + } + + /* we now have a valid SOM-definition + let's create a dummy SOM */ + + som_createnewsom(x, sensors, neuronsX, neuronsY); + + x->rule = rule; + + x->lr=lr[0]; + x->lr_factor=lr[1]; + x->lr_bias=lr[2]; + + x->nb=nb[0]; + x->nb_factor=nb[1]; + x->nb_bias=nb[2]; + + /* read the weights */ + + if ((fscanf(f,"\nweights:\n %f",&dummy)) != 1) { + break; + } + + i=0; + while (i<x->num_neurons) { + j = x->num_sensors; + fp= x->weights[i]; + while (j--) { + *fp++=dummy; + if ((fscanf(f,"%f",&dummy)) != 1) { + break; + } + } + j = x->num_sensors; + i++; + } + + /* finally read the distances */ + if ((fscanf(f,"\ndists:\n %f",&dummy)) != 1) { + break; + } + + i=0; + while (i<x->num_neurons) { + j = x->num_neurons; + fp= x->dist[i]; + while (j--) { + *fp++=dummy; + if ((fscanf(f,"%f",&dummy)) != 1) { + break; + } + } + j = x->num_sensors; + i++; + } + + } + + /* close file */ + if (f) fclose(f); + + +} + +static void som_write(t_som *x, t_symbol *s, int argc, t_atom *argv) +{ /* write a som-file */ + char filnam[MAXPDSTRING]; + char buf[MAXPDSTRING]; + char *text=0; + int textlen; + + FILE *f=0; + + int i; + + if (argc>0) { + x->filename = atom_gensym(argv); + x->defaultfilename = 0; + } + if (x->defaultfilename) error("som_write: writing to default file \"%s\"", x->filename->s_name); + + canvas_makefilename(x->x_canvas, x->filename->s_name, buf, MAXPDSTRING); + sys_bashfilename(x->filename->s_name, filnam); + + while (f==0) { + /* open file */ + if (!(f = fopen(filnam, "w"))) { + error("msgfile : failed to open %s", filnam); + } else { + + /* write header information */ + text=(char *)getbytes(sizeof(char)*MAXPDSTRING); + sprintf(text, "SOM:\n%d %d %d %s\n%.15f %.15f %.15f\n%.15f %.15f %.15f\nweights:\n", + x->num_sensors, x->num_neurX, x->num_neurY, (x->rule==INSTAR)?"INSTAR":(x->rule==OUTSTAR)?"OUTSTAR":"KOHONEN", + x->lr, x->lr_factor, x->lr_bias, + x->nb, x->nb_factor, x->nb_bias); + textlen = strlen(text); + + if (fwrite(text, textlen*sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + + /* write weights */ + for (i=0; i<x->num_neurons; i++) { + int j=x->num_sensors; + t_float *weight = x->weights[i]; + while (j--) { + sprintf(text, " %.15f", *weight++); + textlen=strlen(text); + if (fwrite(text, textlen*sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + } + if (fwrite("\n", sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + } + + /* write dists */ + if (fwrite("dists:\n", 7*sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + for (i=0; i<x->num_neurons; i++) { + int j=x->num_neurons; + t_float *dist = x->dist[i]; + while (j--) { + sprintf(text, " %.15f", *dist++); + textlen=strlen(text); + if (fwrite(text, textlen*sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + } + if (fwrite("\n", sizeof(char), 1, f) < 1) { + error("msgfile : failed to write %s", filnam); break; + } + } + } + } + /* close file */ + if (f) fclose(f); + + freebytes(text, sizeof(text)); +} + + +static void som_help(t_som *x) +{ + post("\nann_som\t:: self orgranized map"); + post("<f1> <f2> <f3>... <fn>\t: train/test som with data" + "\nlearn\t\t:... " + + "\nhelp\t\t: show this help"); + post("creation: \"ann_som <som-file>\": <som-file> defines a file to be loeaded as a som"); +} + + +static void som_print(t_som *x) +{ + char c = (x->defaultfilename)?'\0':'\"'; + post("\nann_som\t:: self orgranized map"); + post("rule=%s\tmode=%s", (x->rule==INSTAR)?"INSTAR":(x->rule==OUTSTAR)?"OUTSTAR":"KOHONEN", (x->mode==TEST)?"TEST":"TRAIN"); + post("file = %c%s%c", c, x->filename->s_name,c ); + post("neurons = %d*%d = %d\tsensors=%d", x->num_neurX, x->num_neurY, x->num_neurons, x->num_sensors); + post("learning-rate : lr=%.15f\tlr_x=%.15f\tlr_o=%.15f", x->lr, x->lr_factor, x->lr_bias); + post("neighbourhood : nb=%.15f\tnb_x=%.15f\tnb_o=%.15f\n", x->nb, x->nb_factor, x->nb_bias); + +} +static void som_free(t_som *x) +{ + som_killsom(x); +} + +static void *som_new(t_symbol *s, int argc, t_atom *argv) +{ + t_som *x = (t_som *)pd_new(som_class); + + outlet_new(&x->x_obj, 0); + + x->rule = INSTAR; + x->mode = TRAIN; + + x->filename = gensym("default.som"); + x->defaultfilename = 1; + + x->num_neurX = 0; + x->num_neurY = 0; + x->num_neurons = 0; + + x->num_sensors = 0; + + x->weights = 0; + x->dist = 0; + + x->lr = 1; + x->lr_factor = 0.999999999; + x->lr_bias = 0; + + x->nb = 10; + x->nb_factor = 0.999999999; + x->nb_bias = 0.999999999; + + x->x_canvas = canvas_getcurrent(); + + + if ((argc==0) || (argv->a_type == A_SYMBOL)) { + /* load the som-file */ + if (argc != 0) x->defaultfilename = 0; + som_read(x, s, argc, argv); + } else { + /* create a new som */ + som_makenewsom(x, s, argc, argv); + } + + return (x); +} + +static void som_setup(void) +{ + som_class = class_new(gensym("ann_som"), (t_newmethod)som_new, + (t_method)som_free, sizeof(t_som), 0, A_GIMME, 0); + + class_addlist(som_class, som_list); + class_addbang(som_class, som_bang); + + class_addmethod(som_class, (t_method)som_makenewsom, gensym("new"), A_GIMME, 0); + class_addmethod(som_class, (t_method)som_init, gensym("init"), A_GIMME, 0); + + class_addmethod(som_class, (t_method)som_learn, gensym("learn"), A_GIMME, 0); + class_addmethod(som_class, (t_method)som_neighbour, gensym("neighbour"), A_GIMME, 0); + + class_addmethod(som_class, (t_method)som_train, gensym("train"), 0); + class_addmethod(som_class, (t_method)som_test, gensym("test"), 0); + class_addmethod(som_class, (t_method)som_rule, gensym("rule"), A_GIMME, 0); + + class_addmethod(som_class, (t_method)som_read, gensym("read"), A_GIMME, 0); + class_addmethod(som_class, (t_method)som_write, gensym("write"), A_GIMME, 0); + + class_addmethod(som_class, (t_method)som_print, gensym("print"), 0); + class_addmethod(som_class, (t_method)som_help, gensym("help"), 0); + class_sethelpsymbol(som_class, gensym("ann/som")); + +} + +void ann_som_setup(void) +{ + som_setup(); +} + diff --git a/src/makefile.irix b/src/makefile.irix new file mode 100644 index 0000000..12272d1 --- /dev/null +++ b/src/makefile.irix @@ -0,0 +1,20 @@ +current: irix5 + +TARGETS = linux \ + ann_som + +SGI5OBJECTS = $(TARGETS:%=%.pd_irix5) + +# ----------------------- IRIX ---------------------------- +.SUFFIXES: .pd_irix5 +SGIINCLUDE = -I../../src + +irix5: $(SGIOBJECTS) + +.c.pd_irix5: + cc -g -w2 -fullwarn -mips2 -DFTS $(SGIINCLUDE) -c $*.c + ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o + rm $*.o + +clean:: + rm *.o obj/* *.pd_irix5 so_locations rm *.pd_linux *~ diff --git a/src/makefile.linux b/src/makefile.linux new file mode 100644 index 0000000..0df06bb --- /dev/null +++ b/src/makefile.linux @@ -0,0 +1,76 @@ +current: all + + +# the ANN-EXTERNAL-makefile +# everything is GnuGPL that should come with the ann.tgz +# NO WARRANTIES FOR ANYTHING +# et cetera +# (l) forum::für::umläute 2001 + +# make sure that the "m_pd.h" is somehow available either by putting it into this +# directory, by adding it's path to the INCLUDE-path or by putting it into an +# already included path, e.g. "/usr/local/include/" + +#these are the user adjustables : adjust them to fit into your system +# PD will install to $(DESTDIR)$(INSTALLL_PREFIX)$(PDLIBDIR), which is /usr/local/lib/pd +# by default +DESTDIR = +INSTALL_PREFIX = /usr/local +PDLIBDIR = /lib/pd +#these were the user adjustables + + +TARGETS = ann \ + ann_som \ + + +# ----------------------- LINUX ---------------------------- +.SUFFIXES: .pd_linux + + +LINUXOBJECTS = $(TARGETS:%=%.o) +ARCH = $(shell uname --machine) + +PD_DIR = $(DESTDIR)$(INSTALL_PREFIX)$(PDLIBDIR) + +ifeq (${ARCH},alpha) +AFLAGS = -mieee -mcpu=ev56 +endif + +LINCLUDE = + +$(LINUXOBJECTS): *.h + +#CFLAGS = -O2 -g -Wall $(LINCLUDE) $(UCFLAGS) $(AFLAGS) +CFLAGS = -O2 -O6 -funroll-loops -mpentiumpro -fomit-frame-pointer -Wall $(LINCLUDE) $(UCFLAGS) $(AFLAGS) + +everything: clean all install distclean + +distclean: + touch dummy.o + touch dummy.pd_linux + touch dummy~ + rm *.o *.pd_linux *~ + +clean: + touch dummy.o + touch dummy.pd_linux + rm *.o *.pd_linux + +all: $(LINUXOBJECTS) + + @echo :: $(LINUXOBJECTS) + + ld -export_dynamic -shared -o ann.pd_linux *.o -lc -lm + strip --strip-unneeded ann.pd_linux + +.c.pd_linux: + cc $(CFLAGS) -O2 -DPD -fPIC $(INCLUDE) -c -o $*.o $*.c + + +install: installdocs + install -m 644 ann.pd_linux $(PD_DIR)/externs + +installdocs: + install -d $(PD_DIR)/doc/5.reference/ann + install -m644 ../examples/* $(PD_DIR)/doc/5.reference/ann |