From 208200ef713d588a1cb5c4d125b2bfccc9a7e2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 19 Sep 2005 14:47:50 +0000 Subject: added a bunch of new objects (from f.zotter); some of them are unstable, some are likely to change in their behaviour (read: not yet for use) svn path=/trunk/externals/iem/iemmatrix/; revision=3598 --- src/mtx_fill.c | 356 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 src/mtx_fill.c (limited to 'src/mtx_fill.c') diff --git a/src/mtx_fill.c b/src/mtx_fill.c new file mode 100644 index 0000000..8e07897 --- /dev/null +++ b/src/mtx_fill.c @@ -0,0 +1,356 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * Copyright (c) 2005, Franz Zotter + * IEM, Graz, Austria + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + */ + + +#include "iemmatrix.h" + +typedef enum { + FILL_SUBMATRIX, + FILL_INDEXED_ELEMENTS +} FillStyle; + +static t_class *mtx_fill_class; + +typedef struct _MTXfill_ MTXfill; +struct _MTXfill_ +{ + t_object x_obj; + int size; + int rows; + int columns; + + int fill_startcol; + int fill_startrow; + + int *index; + int index_size; + int max_index; + + FillStyle fill_type; + + t_outlet *list_outlet; + + t_atom *list_in; + t_atom *list_out; +}; + +static void deleteMTXFill (MTXfill *mtx_fill_obj) +{ + if (mtx_fill_obj->list_in) + freebytes (mtx_fill_obj->list_in, sizeof(t_atom)*(mtx_fill_obj->size+2)); + if (mtx_fill_obj->list_out) + freebytes (mtx_fill_obj->list_out, sizeof(t_atom)*(mtx_fill_obj->size+2)); + if (mtx_fill_obj->index) + freebytes (mtx_fill_obj->list_out, sizeof(int)*(mtx_fill_obj->index_size)); +} + +static void setListConstFloat (int size, t_float f, t_atom *y) +{ + for(;size--;y++) + SETFLOAT(y,f); +} +static void copyList (int size, t_atom *x, t_atom *y) +{ + while(size--) + *y++=*x++; +} +static int copyNonZeroAtomsToIntegerArrayMax (int *size, t_atom *x, int *y) +{ + int idx; + int n = *size; + int max = atom_getint(x); + *size = 0; + for (;n--;x++) { + idx = atom_getint (x); + if (idx) { + size[0]++; + *y++ = idx; + max = (idx > max)?idx:max; + } + } + return max; +} + +static void writeIndexedValuesIntoMatrix (int n, int *index, t_atom *x, t_atom *y) +{ + for (;n--;index++,x++) + if (*index) + y[*index-1] = *x; +} +static void writeFloatIndexedIntoMatrix (int n, int *index, t_float f, t_atom *y) +{ + for (;n--;index++) + if (*index) + SETFLOAT(&y[*index-1], f); +} + +static void mTXFillIndexMatrix (MTXfill *mtx_fill_obj, t_symbol *s, + int argc, t_atom *argv) +{ + int rows = atom_getint (argv++); + int columns = atom_getint (argv++); + int size = rows * columns; + int list_size = argc - 2; + int *index = mtx_fill_obj->index; + + // size check + if (!size) { + post("mtx_fill: invalid dimensions/invalid start index"); + return; + } + + if (list_size == 0) { + if ((rows<1) || (columns<1)){ + post("mtx_fill: row and column indices must be >0"); + return; + } + mtx_fill_obj->fill_startrow = rows; + mtx_fill_obj->fill_startcol = columns; + mtx_fill_obj->fill_type = FILL_SUBMATRIX; + } + else if (list_size mtx_fill_obj->index_size) { + if (!index) + index = (int *) getbytes (sizeof (int) * (size + 2)); + else + index = (int *) resizebytes (index, + sizeof (int) * (mtx_fill_obj->index_size+2), + sizeof (t_atom) * (size + 2)); + mtx_fill_obj->index_size = size; + } + mtx_fill_obj->max_index = + copyNonZeroAtomsToIntegerArrayMax (&size, argv++, index); + if (!size) { + post("mtx_fill: indexing matrix contains zero-values only!!!"); + return; + } + if (size != mtx_fill_obj->index_size) { + index = (int *) resizebytes (index, + sizeof (int) * (mtx_fill_obj->index_size+2), + sizeof (t_atom) * (size + 2)); + mtx_fill_obj->index_size = size; + } + mtx_fill_obj->fill_type = FILL_INDEXED_ELEMENTS; + mtx_fill_obj->index = index; + } +} + +static void *newMTXFill (t_symbol *s, int argc, t_atom *argv) +{ + MTXfill *mtx_fill_obj = (MTXfill *) pd_new (mtx_fill_class); + + mtx_fill_obj->fill_startrow = 1; + mtx_fill_obj->fill_startcol = 1; + mtx_fill_obj->fill_type = FILL_SUBMATRIX; + if (argc) { + if (atom_getsymbol(argv)==gensym("matrix")) + mTXFillIndexMatrix (mtx_fill_obj, s, argc-1, argv+1); + else + post("mtx_fill: creation argument must be 'matrix ' for submatrix filling or 'matrix rows columns [...]' for indexed filling with scalar/matrices"); + } + + mtx_fill_obj->list_outlet = outlet_new (&mtx_fill_obj->x_obj, gensym("matrix")); + inlet_new(&mtx_fill_obj->x_obj, &mtx_fill_obj->x_obj.ob_pd, gensym("matrix"),gensym("fill_mtx")); + inlet_new(&mtx_fill_obj->x_obj, &mtx_fill_obj->x_obj.ob_pd, gensym("matrix"),gensym("index")); + return ((void *) mtx_fill_obj); +} + +static void mTXBigMatrix (MTXfill *mtx_fill_obj, t_symbol *s, + int argc, t_atom *argv) +{ + int rows = atom_getint (argv++); + int columns = atom_getint (argv++); + int size = rows * columns; + int list_size = argc - 2; + t_atom *list_in = mtx_fill_obj->list_in; + t_atom *list_out = mtx_fill_obj->list_out; + + // size check + if (!size) { + post("mtx_fill: invalid dimensions"); + return; + } + else if (list_sizesize) { + if (!list_out) + list_out = (t_atom *) getbytes (sizeof (t_atom) * (size + 2)); + else + list_out = (t_atom *) resizebytes (list_out, + sizeof (t_atom) * (mtx_fill_obj->size+2), + sizeof (t_atom) * (size + 2)); + if (!list_in) + list_in = (t_atom *) getbytes (sizeof (t_atom) * (size + 2)); + else + list_in = (t_atom *) resizebytes (list_in, + sizeof (t_atom) * (mtx_fill_obj->size+2), + sizeof (t_atom) * (size + 2)); + } + + mtx_fill_obj->size = size; + mtx_fill_obj->columns = columns; + mtx_fill_obj->rows = rows; + mtx_fill_obj->list_out = list_out; + mtx_fill_obj->list_in = list_in; + + copyList (size, argv, list_in); +} + + +static void mTXFillBang (MTXfill *mtx_fill_obj) +{ + if (mtx_fill_obj->list_out) + outlet_anything(mtx_fill_obj->list_outlet, gensym("matrix"), + mtx_fill_obj->size+2, mtx_fill_obj->list_out); +} + +static void writeFillMatrixIntoList (int fillrows, const int fillcols, int columns, t_atom *x, t_atom *y) +{ + for (;fillrows--;x+=fillcols,y+=columns) + copyList(fillcols, x, y); +} + +static void mTXFillScalar (MTXfill *mtx_fill_obj, t_float f) +{ + t_atom *list_out = mtx_fill_obj->list_out; + t_atom *list_in = mtx_fill_obj->list_in; + int rows = mtx_fill_obj->rows; + int columns = mtx_fill_obj->columns; + if (mtx_fill_obj->fill_type == FILL_INDEXED_ELEMENTS) { + if (mtx_fill_obj->max_index > mtx_fill_obj->size) { + post("mtx_fill: index matrix index exceeds matrix borders"); + return; + } + else if (mtx_fill_obj->size == 0) { + post("mtx_fill: no matrix defined for filling"); + return; + } + + // main part + list_out += 2; + copyList (mtx_fill_obj->size, list_in, list_out); + + writeFloatIndexedIntoMatrix (mtx_fill_obj->index_size, + mtx_fill_obj->index, f,list_out); + list_out = mtx_fill_obj->list_out; + SETSYMBOL(list_out, gensym("matrix")); + SETFLOAT(list_out, rows); + SETFLOAT(&list_out[1], columns); + outlet_anything(mtx_fill_obj->list_outlet, gensym("matrix"), + mtx_fill_obj->size+2, list_out); + } + else + post("mtx_fill: scalar fill for submatrices not supported yet"); +} + + +static void mTXFillMatrix (MTXfill *mtx_fill_obj, t_symbol *s, + int argc, t_atom *argv) +{ + int fill_rows = atom_getint (argv++); + int fill_columns = atom_getint (argv++); + int fill_size = fill_rows * fill_columns; + int list_size = argc - 2; + int rows = mtx_fill_obj->rows; + int columns = mtx_fill_obj->columns; + t_atom *fill_mtx = argv; + t_atom *list_in = mtx_fill_obj->list_in; + t_atom *list_out = mtx_fill_obj->list_out; + int stopcol = mtx_fill_obj->fill_startcol+fill_columns-1; + int stoprow = mtx_fill_obj->fill_startrow+fill_rows-1; + + // size check + if (!list_size) { + post("mtx_fill: invalid dimensions"); + return; + } + switch (mtx_fill_obj->fill_type) { + case FILL_SUBMATRIX: + if (list_size < fill_size) { + post("mtx_fill: sparse matrix not yet supported: use \"mtx_check\""); + return; + } + if ((stopcol > columns) || + (stoprow > rows)) { + post("mtx_fill: fill matrix index exceeds matrix borders"); + return; + } + break; + case FILL_INDEXED_ELEMENTS: + if (list_size > mtx_fill_obj->index_size) { + post("mtx_fill: fill matrix smaller than indexing vector"); + return; + } + else if (mtx_fill_obj->max_index > mtx_fill_obj->size) { + post("mtx_fill: index matrix index exceeds matrix borders"); + return; + } + break; + } + if (mtx_fill_obj->size == 0) { + post("mtx_fill: no matrix defined for filling"); + return; + } + + + // main part + list_out += 2; + copyList (mtx_fill_obj->size, list_in, list_out); + + switch (mtx_fill_obj->fill_type) { + case FILL_SUBMATRIX: + list_out += columns * (mtx_fill_obj->fill_startrow-1) + + mtx_fill_obj->fill_startcol-1; + writeFillMatrixIntoList (fill_rows, fill_columns, + columns, fill_mtx, list_out); + break; + case FILL_INDEXED_ELEMENTS: + writeIndexedValuesIntoMatrix (mtx_fill_obj->index_size, + mtx_fill_obj->index, fill_mtx,list_out); + break; + } + list_out = mtx_fill_obj->list_out; + SETSYMBOL(list_out, gensym("matrix")); + SETFLOAT(list_out, rows); + SETFLOAT(&list_out[1], columns); + outlet_anything(mtx_fill_obj->list_outlet, gensym("matrix"), + mtx_fill_obj->size+2, list_out); +} + +void mtx_fill_setup (void) +{ + mtx_fill_class = class_new + (gensym("mtx_fill"), + (t_newmethod) newMTXFill, + (t_method) deleteMTXFill, + sizeof (MTXfill), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (mtx_fill_class, (t_method) mTXFillBang); + class_addmethod (mtx_fill_class, (t_method) mTXFillMatrix, gensym("matrix"), A_GIMME,0); + class_addmethod (mtx_fill_class, (t_method) mTXBigMatrix, gensym("fill_mtx"), A_GIMME,0); + class_addmethod (mtx_fill_class, (t_method) mTXFillIndexMatrix, gensym("index"), A_GIMME,0); + class_addfloat (mtx_fill_class, (t_method) mTXFillScalar); + class_sethelpsymbol (mtx_fill_class, gensym("iemmatrix/mtx_fill")); +} + +void iemtx_fill_setup(void){ + mtx_fill_setup(); +} -- cgit v1.2.1