aboutsummaryrefslogtreecommitdiff
path: root/src/mtx_fill.c
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-09-19 14:47:50 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-09-19 14:47:50 +0000
commit208200ef713d588a1cb5c4d125b2bfccc9a7e2ce (patch)
tree29a88daf24459282860deb1b7bb684c5eaf49103 /src/mtx_fill.c
parent38ee08dc2ce882e4fa8266f0d07fae258d098991 (diff)
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
Diffstat (limited to 'src/mtx_fill.c')
-rw-r--r--src/mtx_fill.c356
1 files changed, 356 insertions, 0 deletions
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<size) {
+ post("mtx_fill: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+ else {
+ if (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 <startrow> <startcol>' 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_size<size) {
+ post("mtx_fill: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size != mtx_fill_obj->size) {
+ 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();
+}