aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/iemmatrix_sources.c12
-rw-r--r--src/iemmatrix_sources.h12
-rw-r--r--src/mtx_colon.c114
-rw-r--r--src/mtx_conv.c337
-rw-r--r--src/mtx_cumsum.c238
-rw-r--r--src/mtx_diff.c232
-rw-r--r--src/mtx_fill.c356
-rw-r--r--src/mtx_find.c286
-rw-r--r--src/mtx_index.c213
-rw-r--r--src/mtx_minmax.c284
-rw-r--r--src/mtx_not.c88
-rw-r--r--src/mtx_repmat.c161
-rw-r--r--src/mtx_reverse.c176
-rw-r--r--src/mtx_sort.c325
14 files changed, 2834 insertions, 0 deletions
diff --git a/src/iemmatrix_sources.c b/src/iemmatrix_sources.c
index 9b9b46e..1777aca 100644
--- a/src/iemmatrix_sources.c
+++ b/src/iemmatrix_sources.c
@@ -18,19 +18,26 @@ void iemmatrix_sources_setup(void)
iemtx_check_setup(); /* mtx_check.c */
iemtx_cholesky_setup(); /* mtx_cholesky.c */
iemtx_col_setup(); /* mtx_col.c */
+ iemtx_colon_setup(); /* mtx_colon.c */
+ iemtx_conv_setup(); /* mtx_conv.c */
iemtx_cos_setup(); /* mtx_cos.c */
+ iemtx_cumsum_setup(); /* mtx_cumsum.c */
iemtx_dbtorms_setup(); /* mtx_dbtorms.c */
iemtx_diag_setup(); /* mtx_diag.c */
iemtx_diegg_setup(); /* mtx_diegg.c */
+ iemtx_diff_setup(); /* mtx_diff.c */
iemtx_distance2_setup(); /* mtx_distance2.c */
iemtx_egg_setup(); /* mtx_egg.c */
iemtx_element_setup(); /* mtx_element.c */
iemtx_eq_setup(); /* mtx_eq.c */
iemtx_exp_setup(); /* mtx_exp.c */
iemtx_eye_setup(); /* mtx_eye.c */
+ iemtx_fill_setup(); /* mtx_fill.c */
+ iemtx_find_setup(); /* mtx_find.c */
iemtx_gauss_setup(); /* mtx_gauss.c */
iemtx_ge_setup(); /* mtx_ge.c */
iemtx_gt_setup(); /* mtx_gt.c */
+ iemtx_index_setup(); /* mtx_index.c */
iemtx_int_setup(); /* mtx_int.c */
iemtx_inverse_setup(); /* mtx_inverse.c */
iemtx_le_setup(); /* mtx_le.c */
@@ -40,9 +47,11 @@ void iemmatrix_sources_setup(void)
iemtx_max2_setup(); /* mtx_max2.c */
iemtx_mean_setup(); /* mtx_mean.c */
iemtx_min2_setup(); /* mtx_min2.c */
+ iemtx_minmax_setup(); /* mtx_minmax.c */
iemtx_mul_setup(); /* mtx_mul.c */
iemtx_mul__setup(); /* mtx_mul~.c */
iemtx_neq_setup(); /* mtx_neq.c */
+ iemtx_not_setup(); /* mtx_not.c */
iemtx_ones_setup(); /* mtx_ones.c */
iemtx_or_setup(); /* mtx_or.c */
iemtx_pivot_setup(); /* mtx_pivot.c */
@@ -50,13 +59,16 @@ void iemmatrix_sources_setup(void)
iemtx_print_setup(); /* mtx_print.c */
iemtx_prod_setup(); /* mtx_prod.c */
iemtx_rand_setup(); /* mtx_rand.c */
+ iemtx_repmat_setup(); /* mtx_repmat.c */
iemtx_resize_setup(); /* mtx_resize.c */
+ iemtx_reverse_setup(); /* mtx_reverse.c */
iemtx_rmstodb_setup(); /* mtx_rmstodb.c */
iemtx_roll_setup(); /* mtx_roll.c */
iemtx_row_setup(); /* mtx_row.c */
iemtx_scroll_setup(); /* mtx_scroll.c */
iemtx_sin_setup(); /* mtx_sin.c */
iemtx_size_setup(); /* mtx_size.c */
+ iemtx_sort_setup(); /* mtx_sort.c */
iemtx_sub_setup(); /* mtx_sub.c */
iemtx_sum_setup(); /* mtx_sum.c */
iemtx_trace_setup(); /* mtx_trace.c */
diff --git a/src/iemmatrix_sources.h b/src/iemmatrix_sources.h
index a8324a4..aea3694 100644
--- a/src/iemmatrix_sources.h
+++ b/src/iemmatrix_sources.h
@@ -16,19 +16,26 @@ void iemtx_bitright_setup(void); /* mtx_bitright.c */
void iemtx_check_setup(void); /* mtx_check.c */
void iemtx_cholesky_setup(void); /* mtx_cholesky.c */
void iemtx_col_setup(void); /* mtx_col.c */
+void iemtx_colon_setup(void); /* mtx_colon.c */
+void iemtx_conv_setup(void); /* mtx_conv.c */
void iemtx_cos_setup(void); /* mtx_cos.c */
+void iemtx_cumsum_setup(void); /* mtx_cumsum.c */
void iemtx_dbtorms_setup(void); /* mtx_dbtorms.c */
void iemtx_diag_setup(void); /* mtx_diag.c */
void iemtx_diegg_setup(void); /* mtx_diegg.c */
+void iemtx_diff_setup(void); /* mtx_diff.c */
void iemtx_distance2_setup(void); /* mtx_distance2.c */
void iemtx_egg_setup(void); /* mtx_egg.c */
void iemtx_element_setup(void); /* mtx_element.c */
void iemtx_eq_setup(void); /* mtx_eq.c */
void iemtx_exp_setup(void); /* mtx_exp.c */
void iemtx_eye_setup(void); /* mtx_eye.c */
+void iemtx_fill_setup(void); /* mtx_fill.c */
+void iemtx_find_setup(void); /* mtx_find.c */
void iemtx_gauss_setup(void); /* mtx_gauss.c */
void iemtx_ge_setup(void); /* mtx_ge.c */
void iemtx_gt_setup(void); /* mtx_gt.c */
+void iemtx_index_setup(void); /* mtx_index.c */
void iemtx_int_setup(void); /* mtx_int.c */
void iemtx_inverse_setup(void); /* mtx_inverse.c */
void iemtx_le_setup(void); /* mtx_le.c */
@@ -38,9 +45,11 @@ void iemtx_matrix_setup(void); /* mtx_matrix.c */
void iemtx_max2_setup(void); /* mtx_max2.c */
void iemtx_mean_setup(void); /* mtx_mean.c */
void iemtx_min2_setup(void); /* mtx_min2.c */
+void iemtx_minmax_setup(void); /* mtx_minmax.c */
void iemtx_mul_setup(void); /* mtx_mul.c */
void iemtx_mul__setup(void); /* mtx_mul~.c */
void iemtx_neq_setup(void); /* mtx_neq.c */
+void iemtx_not_setup(void); /* mtx_not.c */
void iemtx_ones_setup(void); /* mtx_ones.c */
void iemtx_or_setup(void); /* mtx_or.c */
void iemtx_pivot_setup(void); /* mtx_pivot.c */
@@ -48,13 +57,16 @@ void iemtx_pow_setup(void); /* mtx_pow.c */
void iemtx_print_setup(void); /* mtx_print.c */
void iemtx_prod_setup(void); /* mtx_prod.c */
void iemtx_rand_setup(void); /* mtx_rand.c */
+void iemtx_repmat_setup(void); /* mtx_repmat.c */
void iemtx_resize_setup(void); /* mtx_resize.c */
+void iemtx_reverse_setup(void); /* mtx_reverse.c */
void iemtx_rmstodb_setup(void); /* mtx_rmstodb.c */
void iemtx_roll_setup(void); /* mtx_roll.c */
void iemtx_row_setup(void); /* mtx_row.c */
void iemtx_scroll_setup(void); /* mtx_scroll.c */
void iemtx_sin_setup(void); /* mtx_sin.c */
void iemtx_size_setup(void); /* mtx_size.c */
+void iemtx_sort_setup(void); /* mtx_sort.c */
void iemtx_sub_setup(void); /* mtx_sub.c */
void iemtx_sum_setup(void); /* mtx_sum.c */
void iemtx_trace_setup(void); /* mtx_trace.c */
diff --git a/src/mtx_colon.c b/src/mtx_colon.c
new file mode 100644
index 0000000..c6ce8ff
--- /dev/null
+++ b/src/mtx_colon.c
@@ -0,0 +1,114 @@
+/*
+ * 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"
+
+static t_class *mtx_colon_class;
+
+typedef struct _MTXColon_ MTXColon;
+struct _MTXColon_
+{
+ t_object x_obj;
+ int size;
+
+ t_atom *list_out;
+ t_outlet *list_outlet;
+};
+
+static void deleteMTXColon (MTXColon *mtx_colon_obj)
+{
+ if (mtx_colon_obj->list_out)
+ freebytes (mtx_colon_obj->list_out, sizeof(t_atom)*(mtx_colon_obj->size+2));
+}
+
+static void *newMTXColon (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXColon *mtx_colon_obj = (MTXColon *) pd_new (mtx_colon_class);
+
+ mtx_colon_obj->list_outlet = outlet_new (&mtx_colon_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_colon_obj);
+}
+
+static void mTXColonBang (MTXColon *mtx_colon_obj)
+{
+ if (mtx_colon_obj->list_out)
+ outlet_anything(mtx_colon_obj->list_outlet, gensym("matrix"),
+ mtx_colon_obj->size+2, mtx_colon_obj->list_out);
+}
+
+static void mTXColonList (MTXColon *mtx_colon_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ int size;
+ t_float startval;
+ t_float stopval;
+ t_float step;
+ t_atom *list_out = mtx_colon_obj->list_out;
+ if (argc == 3) {
+ startval = atom_getfloat(argv++);
+ step = atom_getfloat(argv++);
+ stopval = atom_getfloat(argv++);
+ }
+ else if (argc == 2) {
+ startval = atom_getfloat(argv++);
+ stopval = atom_getfloat(argv++);
+ step = 1.0f;
+ }
+ else {
+ post("mtx_colon: wrong number of input arguments");
+ return;
+ }
+
+ size = (int)((stopval- startval + step) / step);
+ //post("startval %f stopval %f step %f, size %d",startval, stopval, step, size);
+ if (size) {
+ if (size!=mtx_colon_obj->size) {
+ if (list_out)
+ list_out = (t_atom *) resizebytes (list_out,
+ sizeof(t_atom)*(mtx_colon_obj->size+2),
+ sizeof(t_atom)*(size+2));
+ else
+ list_out = (t_atom*) getbytes (sizeof(t_atom)*(size+2));
+ mtx_colon_obj->size = size;
+ }
+ mtx_colon_obj->list_out = list_out;
+
+ SETFLOAT (&list_out[0],1.0f);
+ SETFLOAT (&list_out[1],(t_float)size);
+ list_out += 2;
+ for (;size--;list_out++,startval+=step)
+ SETFLOAT(list_out,startval);
+
+ mTXColonBang (mtx_colon_obj);
+ }
+}
+
+void mtx_colon_setup (void)
+{
+ mtx_colon_class = class_new
+ (gensym("mtx_colon"),
+ (t_newmethod) newMTXColon,
+ (t_method) deleteMTXColon,
+ sizeof (MTXColon),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_colon_class, (t_method) mTXColonBang);
+ class_addlist (mtx_colon_class, (t_method) mTXColonList);
+ class_addcreator ((t_newmethod) newMTXColon, gensym("mtx_:"), A_GIMME, 0);
+ class_sethelpsymbol (mtx_colon_class, gensym("iemmatrix/mtx_colon"));
+}
+
+void iemtx_colon_setup(void){
+ mtx_colon_setup();
+}
diff --git a/src/mtx_conv.c b/src/mtx_conv.c
new file mode 100644
index 0000000..6af8abc
--- /dev/null
+++ b/src/mtx_conv.c
@@ -0,0 +1,337 @@
+/*
+ * 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"
+
+static t_class *mtx_conv_class;
+
+typedef struct _MTXConv_ MTXConv;
+struct _MTXConv_
+{
+ t_object x_obj;
+ int size;
+ int rows;
+ int columns;
+ int rows_k;
+ int columns_k;
+ int size_k;
+ int rows_y;
+ int columns_y;
+ int size_y;
+ t_float renorm_fac;
+
+ t_float **x;
+ t_float **k;
+ t_float **y;
+
+ t_outlet *list_outlet;
+
+ t_atom *list;
+};
+
+static t_float **getTFloatMatrix (int rows, int columns)
+{
+ t_float **matrix = (t_float **) getbytes
+ (sizeof (t_float *) * columns);
+ t_float **mtx = matrix;
+
+ while (columns--)
+ if (!(*matrix++ = (t_float *) getbytes
+ (sizeof (t_float) * rows)))
+ post("an error has occured :)");
+ return mtx;
+}
+
+static void deleteTFloatMatrix (t_float **matrix, int rows, int columns)
+{
+ int n = columns;
+ t_float **matr = matrix;
+ if (matr) {
+ while (n--)
+ if (*matr)
+ freebytes (*matr++, sizeof(t_float) * rows);
+ freebytes (matrix, sizeof(t_float*) * columns);
+ }
+}
+
+
+static t_float **resizeTFloatMatrix (t_float **old, int rows_old, int columns_old,
+ int rows_new, int columns_new)
+{
+ t_float **mtx = old;
+ int count1, count2;
+ post("resizing from %dx%d to %dx%d", rows_old, columns_old, rows_new, columns_new);
+
+ if ((rows_new == 0)||(columns_new == 0)) {
+ deleteTFloatMatrix (old, rows_old, columns_old);
+ old = 0;
+ return;
+ }
+ // 1. if rows_old>rows_new: old row disposal
+ if (rows_old>rows_new)
+ for (count1 = (rows_old - rows_new), mtx += rows_new;
+ count1--; mtx++)
+ freebytes (*mtx, sizeof(t_float) * columns_old);
+ // 2. resize row (double) pointer
+ mtx = old = (t_float **) resizebytes(old, sizeof(t_float*) * rows_old,
+ sizeof(t_float*) * rows_new);
+ // 3. resizing rows if new size is smaller
+ if (rows_old>rows_new)
+ for (count1 = rows_new; count1--; mtx++)
+ *mtx = (t_float *) resizebytes (*mtx, sizeof(t_float) * columns_old,
+ sizeof(t_float) * columns_new);
+ else { // 4. resizing old rows if new size is bigger, allocating new rows
+ for (count1 = rows_old; count1--; mtx++)
+ *mtx = (t_float *) resizebytes (*mtx, sizeof(t_float) * columns_old,
+ sizeof(t_float) * columns_new);
+ for (count1 = (rows_new - rows_old); count1--; mtx++)
+ *mtx = (t_float *) getbytes (sizeof(t_float) * columns_new);
+ }
+ post("return resize");
+ return old;
+}
+
+static void deleteMTXConv (MTXConv *mtx_conv_obj)
+{
+ int count = mtx_conv_obj->rows;
+ deleteTFloatMatrix (mtx_conv_obj->k, mtx_conv_obj->rows_k, mtx_conv_obj->columns_k);
+ deleteTFloatMatrix (mtx_conv_obj->x, mtx_conv_obj->rows, mtx_conv_obj->columns);
+ deleteTFloatMatrix (mtx_conv_obj->y, mtx_conv_obj->rows_y, mtx_conv_obj->columns_y);
+ if (mtx_conv_obj->list)
+ freebytes (mtx_conv_obj->list, sizeof(t_float) * (mtx_conv_obj->size_y + 2));
+
+ mtx_conv_obj->k = 0;
+ mtx_conv_obj->x = 0;
+ mtx_conv_obj->y = 0;
+ mtx_conv_obj->list = 0;
+}
+
+static void *newMTXConv (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXConv *mtx_conv_obj = (MTXConv *) pd_new (mtx_conv_class);
+ mtx_conv_obj->list_outlet = outlet_new (&mtx_conv_obj->x_obj, gensym("matrix"));
+ inlet_new(&mtx_conv_obj->x_obj, &mtx_conv_obj->x_obj.ob_pd, gensym("matrix"),gensym(""));
+ mtx_conv_obj->size = 0;
+ mtx_conv_obj->rows = 0;
+ mtx_conv_obj->columns = 0;
+ mtx_conv_obj->size_y = 0;
+ mtx_conv_obj->rows_y = 0;
+ mtx_conv_obj->columns_y = 0;
+ mtx_conv_obj->size_k = 0;
+ mtx_conv_obj->rows_k = 0;
+ mtx_conv_obj->columns_k = 0;
+ return ((void *) mtx_conv_obj);
+}
+
+static void mTXConvBang (MTXConv *mtx_conv_obj)
+{
+ if (mtx_conv_obj->list)
+ outlet_anything(mtx_conv_obj->list_outlet, gensym("matrix"), mtx_conv_obj->size+2, mtx_conv_obj->list);
+}
+
+static void zeroFloatArray (int n, t_float *f)
+{
+ while (n--)
+ *f++ = 0.0f;
+}
+static void zeroTFloatMatrix (t_float **mtx, int rows, int columns)
+{
+ while (rows--)
+ zeroFloatArray (columns, *mtx++);
+}
+
+static void writeFloatIntoList (int n, t_atom *l, t_float *f)
+{
+ for (;n--;f++, l++)
+ SETFLOAT (l, *f);
+}
+static void readFloatFromList (int n, t_atom *l, t_float *f)
+{
+ while (n--)
+ *f++ = atom_getfloat (l++);
+}
+static void scaleVector (int n, t_float *x, t_float *y, t_float k)
+{
+ while (n--)
+ *y++ = k * *x++;
+}
+static void addWeightedVector (int n, t_float *x, t_float *y, t_float k)
+{
+ while (n--)
+ *y++ += k * *y++;
+}
+static void readMatrixFromList (int rows, int columns, t_atom *l, t_float **mtx)
+{
+ for (;rows--; l+=columns)
+ readFloatFromList (columns, l, *mtx++);
+}
+static void writeMatrixIntoList (int rows, int columns, t_atom *l, t_float **mtx)
+{
+ for (;rows--; l+=columns)
+ writeFloatIntoList (columns, l, *mtx++);
+}
+
+static void mTXConvKernelMatrix (MTXConv *mtx_conv_obj, t_symbol *s, int argc,
+ t_atom *argv)
+{
+ int rows_k = atom_getint (argv++);
+ int columns_k = atom_getint (argv++);
+ int in_size = argc-2;
+ int size_k = rows_k * columns_k;
+ t_float **k = mtx_conv_obj->k;
+
+ if (!size_k)
+ post ("mtx_conv: invalid matrix dimensions!");
+ else if (in_size < size_k)
+ post("mtx_conv: sparse matrix not yet supported: use \"mtx_check\"");
+ else if ((rows_k != mtx_conv_obj->rows_k) || (columns_k != mtx_conv_obj->columns_k)) {
+ if (k)
+ k = resizeTFloatMatrix (k, mtx_conv_obj->rows_k, mtx_conv_obj->columns_k,
+ rows_k, columns_k);
+ else
+ k = getTFloatMatrix (rows_k, columns_k);
+
+ mtx_conv_obj->rows_k = rows_k;
+ mtx_conv_obj->columns_k = columns_k;
+
+ readMatrixFromList (rows_k, columns_k, argv, k);
+
+ mtx_conv_obj->k = k;
+ mtx_conv_obj->size_k = size_k;
+ }
+ else
+ readMatrixFromList (rows_k, columns_k, argv, k);
+}
+static void convolveRow (int columns, int columns_c, t_float *x, t_float *c, t_float *y)
+{
+ int n,k,count;
+ for (k = 0; k < columns_c; k++)
+ for (n = k, count = columns; count--; n++)
+ y[n] += x[n-k] * c[k];
+}
+
+static void convolveMtx (int rows, int columns, int rows_c, int columns_c,
+ t_float **x, t_float **c, t_float **y)
+{
+ int n,k,count;
+ zeroTFloatMatrix (y, rows+rows_c-1, columns+columns_c-1);
+ for (k = 0; k < rows_c; k++)
+ for (n = k, count = rows; count--; n++)
+ convolveRow (columns, columns_c, x[n-k], c[k], y[n]);
+}
+
+
+static void mTXConvMatrix (MTXConv *mtx_conv_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ int rows = atom_getint (argv++);
+ int columns = atom_getint (argv++);
+ int size = rows * columns;
+ int rows_k = mtx_conv_obj->rows_k;
+ int columns_k = mtx_conv_obj->columns_k;
+ int size_k = mtx_conv_obj->size_k;
+ int in_size = argc-2;
+ int rows_y;
+ int columns_y;
+ int size_y = mtx_conv_obj->size_y;
+ t_atom *list_ptr = mtx_conv_obj->list;
+ t_float **x = mtx_conv_obj->x;
+ t_float **y = mtx_conv_obj->y;
+ t_float **k = mtx_conv_obj->k;
+ t_float *ptr1;
+ t_float *ptr2;
+ int row_count;
+ int offset1;
+ int offset2;
+ int count;
+
+ // fftsize check
+ if (!size){
+ post("mtx_conv: invalid dimensions");
+ return;
+ } else if (in_size<size) {
+ post("mtx_conv: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ } else if (!size_k) {
+ post("mtx_conv: no valid filter kernel defined");
+ return;
+ }
+
+ post("1");
+
+ if ((mtx_conv_obj->rows != rows)||(mtx_conv_obj->columns != columns)) {
+ if (x)
+ x = resizeTFloatMatrix (x, mtx_conv_obj->rows, mtx_conv_obj->columns,
+ rows, columns);
+ else
+ x = getTFloatMatrix (rows, columns);
+ mtx_conv_obj->x = x;
+ mtx_conv_obj->size = size;
+ mtx_conv_obj->rows = rows;
+ mtx_conv_obj->columns = columns;
+ }
+ post("2");
+ rows_y = rows+rows_k-1;
+ columns_y = columns+columns_k-1;
+ if ((mtx_conv_obj->rows_y != rows_y)||(mtx_conv_obj->columns_y != columns_y)) {
+ size_y = rows_y * columns_y;
+ if (y)
+ y = resizeTFloatMatrix (y, mtx_conv_obj->rows_y, mtx_conv_obj->columns_y,
+ rows_y, columns_y);
+ else
+ y = getTFloatMatrix (rows_y, columns_y);
+ if (list_ptr)
+ list_ptr = (t_atom *) resizebytes (list_ptr, sizeof(t_atom) * (mtx_conv_obj->size_y+2),
+ sizeof (t_atom) * (size_y+2));
+ else
+ list_ptr = (t_atom *) getbytes (sizeof (t_atom) * (size_y+2));
+ mtx_conv_obj->size_y = size_y;
+ mtx_conv_obj->rows_y = rows_y;
+ mtx_conv_obj->columns_y = columns_y;
+ mtx_conv_obj->y = y;
+ mtx_conv_obj->list = list_ptr;
+ }
+ post("3");
+ // main part
+ readMatrixFromList (rows, columns, argv, x);
+ post("4");
+ convolveMtx (rows, columns, rows_k, columns_k, x, k, y);
+ post("5");
+ writeMatrixIntoList (rows_y, columns_y, list_ptr+2, y);
+ post("6");
+ SETSYMBOL(list_ptr, gensym("matrix"));
+ SETFLOAT(list_ptr, rows_y);
+ SETFLOAT(&list_ptr[1], columns_y);
+ outlet_anything(mtx_conv_obj->list_outlet, gensym("matrix"),
+ size_y+2, list_ptr);
+ post("7");
+}
+
+void mtx_conv_setup (void)
+{
+ mtx_conv_class = class_new
+ (gensym("mtx_conv"),
+ (t_newmethod) newMTXConv,
+ (t_method) deleteMTXConv,
+ sizeof (MTXConv),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_conv_class, (t_method) mTXConvBang);
+ class_addmethod (mtx_conv_class, (t_method) mTXConvMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_conv_class, (t_method) mTXConvKernelMatrix, gensym(""), A_GIMME,0);
+ class_sethelpsymbol (mtx_conv_class, gensym("iemmatrix/mtx_conv"));
+}
+
+void iemtx_conv_setup(void){
+ mtx_conv_setup();
+}
diff --git a/src/mtx_cumsum.c b/src/mtx_cumsum.c
new file mode 100644
index 0000000..a5c12ba
--- /dev/null
+++ b/src/mtx_cumsum.c
@@ -0,0 +1,238 @@
+/*
+ * 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"
+
+static t_class *mtx_cumsum_class;
+
+typedef struct _MTXCumsum_ MTXCumsum;
+struct _MTXCumsum_
+{
+ t_object x_obj;
+ int rows;
+ int columns;
+ int size;
+ int cumsum_dimension;
+ int cumsum_direction;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+ t_float *x;
+ t_float *y;
+};
+
+static void deleteMTXCumsum (MTXCumsum *mtx_cumsum_obj)
+{
+ if (mtx_cumsum_obj->list_out)
+ freebytes (mtx_cumsum_obj->list_out, sizeof(t_atom)*(mtx_cumsum_obj->size+2));
+ if (mtx_cumsum_obj->x)
+ freebytes (mtx_cumsum_obj->x, sizeof(t_float)*(mtx_cumsum_obj->size));
+ if (mtx_cumsum_obj->y)
+ freebytes (mtx_cumsum_obj->y, sizeof(t_float)*(mtx_cumsum_obj->size));
+}
+
+static void mTXSetCumsumDirection (MTXCumsum *mtx_cumsum_obj, t_float c_dir)
+{
+ int direction = (int) c_dir;
+ mtx_cumsum_obj->cumsum_direction = (direction==-1)?direction:1;
+}
+static void mTXSetCumsumDimension (MTXCumsum *mtx_cumsum_obj, t_float c_dim)
+{
+ int dimension = (int) c_dim;
+ mtx_cumsum_obj->cumsum_dimension = (dimension==2)?dimension:1;
+}
+
+static void *newMTXCumsum (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXCumsum *mtx_cumsum_obj = (MTXCumsum *) pd_new (mtx_cumsum_class);
+ int c_dir = 1;
+ int c_dim = 1;
+
+ mtx_cumsum_obj->cumsum_dimension = c_dim;
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mTXSetCumsumDirection (mtx_cumsum_obj, (t_float) c_dir);
+ mTXSetCumsumDimension (mtx_cumsum_obj, (t_float) c_dim);
+
+ mtx_cumsum_obj->list_outlet = outlet_new (&mtx_cumsum_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_cumsum_obj);
+}
+
+static void mTXCumsumBang (MTXCumsum *mtx_cumsum_obj)
+{
+ if (mtx_cumsum_obj->list_out)
+ outlet_anything(mtx_cumsum_obj->list_outlet, gensym("matrix"),
+ mtx_cumsum_obj->size+2, mtx_cumsum_obj->list_out);
+}
+
+static void writeFloatIntoList (int n, t_atom *l, t_float *f)
+{
+ for (;n--;f++, l++)
+ SETFLOAT (l, *f);
+}
+static void readFloatFromList (int n, t_atom *l, t_float *f)
+{
+ while (n--)
+ *f++ = atom_getfloat (l++);
+}
+static void readFloatFromListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ *f = atom_getfloat (ptr);
+}
+static void writeFloatIntoListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ SETFLOAT(ptr,*f);
+}
+
+static void cumSum (int n, t_float *x, t_float *y)
+{
+ t_float accu = 0.0f;
+ for (;n--; x++, y++) {
+ accu += *x;
+ *y = accu;
+ }
+}
+static void cumSumReverse (int n, t_float *x, t_float *y)
+{
+ t_float accu = 0.0f;
+ for (;n--; x--, y--) {
+ accu += *x;
+ *y = accu;
+ }
+}
+
+static void mTXCumsumMatrix (MTXCumsum *mtx_cumsum_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_ptr = argv;
+ t_atom *list_out = mtx_cumsum_obj->list_out;
+ t_float *x = mtx_cumsum_obj->x;
+ t_float *y = mtx_cumsum_obj->y;
+ int count;
+
+ // size check
+ if (!size) {
+ post("mtx_cumsum: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_cumsum: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+ else if ((!x)||(!list_out)||(!y)) {
+ if (!x)
+ x = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!y)
+ y = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!list_out)
+ list_out = (t_atom *) getbytes (sizeof (t_atom) * (size+2));
+ }
+ else if (size != mtx_cumsum_obj->size) {
+ x = (t_float *) resizebytes (x,
+ sizeof (t_float) * (mtx_cumsum_obj->size),
+ sizeof (t_float) * (size));
+ y = (t_float *) resizebytes (y,
+ sizeof (t_float) * (mtx_cumsum_obj->size),
+ sizeof (t_float) * (size));
+ list_out = (t_atom *) resizebytes (list_out,
+ sizeof (t_atom) * (mtx_cumsum_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+ mtx_cumsum_obj->size = size;
+ mtx_cumsum_obj->rows = rows;
+ mtx_cumsum_obj->columns = columns;
+ mtx_cumsum_obj->list_out = list_out;
+ mtx_cumsum_obj->x = x;
+ mtx_cumsum_obj->y = y;
+
+ // main part
+ // reading matrix from inlet
+ if (mtx_cumsum_obj->cumsum_dimension == 2) {
+ readFloatFromListModulo (size, columns, list_ptr, x);
+ columns = mtx_cumsum_obj->rows;
+ rows = mtx_cumsum_obj->columns;
+ }
+ else
+ readFloatFromList (size, list_ptr, x);
+
+ // calculating cumsum
+ if (mtx_cumsum_obj->cumsum_direction == -1) {
+ x += columns-1;
+ y += columns-1;
+ for (count = rows; count--; x += columns, y += columns)
+ cumSumReverse (columns,x,y);
+ }
+ else
+ for (count = rows; count--; x += columns, y += columns)
+ cumSum (columns,x,y);
+ x = mtx_cumsum_obj->x;
+ y = mtx_cumsum_obj->y;
+
+ // writing matrix to outlet
+ if (mtx_cumsum_obj->cumsum_dimension == 2) {
+ columns = mtx_cumsum_obj->columns;
+ rows = mtx_cumsum_obj->rows;
+ writeFloatIntoListModulo (size, columns, list_out+2, y);
+ }
+ else
+ writeFloatIntoList (size, list_out+2, y);
+
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, rows);
+ SETFLOAT(&list_out[1], columns);
+ outlet_anything(mtx_cumsum_obj->list_outlet, gensym("matrix"),
+ mtx_cumsum_obj->size+2, list_out);
+}
+
+void mtx_cumsum_setup (void)
+{
+ mtx_cumsum_class = class_new
+ (gensym("mtx_cumsum"),
+ (t_newmethod) newMTXCumsum,
+ (t_method) deleteMTXCumsum,
+ sizeof (MTXCumsum),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_cumsum_class, (t_method) mTXCumsumBang);
+ class_addmethod (mtx_cumsum_class, (t_method) mTXCumsumMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_cumsum_class, (t_method) mTXSetCumsumDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_addmethod (mtx_cumsum_class, (t_method) mTXSetCumsumDirection, gensym("direction"), A_DEFFLOAT,0);
+ class_sethelpsymbol (mtx_cumsum_class, gensym("iemmatrix/mtx_cumsum"));
+}
+
+void iemtx_cumsum_setup(void){
+ mtx_cumsum_setup();
+}
diff --git a/src/mtx_diff.c b/src/mtx_diff.c
new file mode 100644
index 0000000..3f491ad
--- /dev/null
+++ b/src/mtx_diff.c
@@ -0,0 +1,232 @@
+/*
+ * 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"
+
+static t_class *mtx_diff_class;
+
+typedef struct _MTXdiff_ MTXdiff;
+struct _MTXdiff_
+{
+ t_object x_obj;
+ int rows;
+ int columns;
+ int size;
+ int diff_dimension;
+ int diff_direction;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+ t_float *x;
+ t_float *y;
+};
+
+static void deleteMTXdiff (MTXdiff *mtx_diff_obj)
+{
+ if (mtx_diff_obj->list_out)
+ freebytes (mtx_diff_obj->list_out, sizeof(t_atom)*(mtx_diff_obj->size+2));
+ if (mtx_diff_obj->x)
+ freebytes (mtx_diff_obj->x, sizeof(t_float)*(mtx_diff_obj->size));
+ if (mtx_diff_obj->y)
+ freebytes (mtx_diff_obj->y, sizeof(t_float)*(mtx_diff_obj->size));
+}
+
+static void mTXSetdiffDirection (MTXdiff *mtx_diff_obj, t_float c_dir)
+{
+ int direction = (int) c_dir;
+ mtx_diff_obj->diff_direction = (direction==-1)?direction:1;
+}
+static void mTXSetdiffDimension (MTXdiff *mtx_diff_obj, t_float c_dim)
+{
+ int dimension = (int) c_dim;
+ mtx_diff_obj->diff_dimension = (dimension==2)?dimension:1;
+}
+
+static void *newMTXdiff (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXdiff *mtx_diff_obj = (MTXdiff *) pd_new (mtx_diff_class);
+ int c_dir = 1;
+ int c_dim = 1;
+
+ mtx_diff_obj->diff_dimension = c_dim;
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mTXSetdiffDirection (mtx_diff_obj, (t_float) c_dir);
+ mTXSetdiffDimension (mtx_diff_obj, (t_float) c_dim);
+
+ mtx_diff_obj->list_outlet = outlet_new (&mtx_diff_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_diff_obj);
+}
+
+static void mTXdiffBang (MTXdiff *mtx_diff_obj)
+{
+ if (mtx_diff_obj->list_out)
+ outlet_anything(mtx_diff_obj->list_outlet, gensym("matrix"),
+ mtx_diff_obj->size+2, mtx_diff_obj->list_out);
+}
+
+static void writeFloatIntoList (int n, t_atom *l, t_float *f)
+{
+ for (;n--;f++, l++)
+ SETFLOAT (l, *f);
+}
+static void readFloatFromList (int n, t_atom *l, t_float *f)
+{
+ while (n--)
+ *f++ = atom_getfloat (l++);
+}
+static void readFloatFromListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ *f = atom_getfloat (ptr);
+}
+static void writeFloatIntoListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ SETFLOAT(ptr,*f);
+}
+
+static void diff (int n, t_float *x, t_float *y)
+{
+ *y++ = *x++;
+ for (;--n; x++, y++)
+ *y = *x - *(x-1);
+}
+static void diffReverse (int n, t_float *x, t_float *y)
+{
+ *y-- = *x--;
+ for (;--n; x--, y--)
+ *y = *x - *(x+1);
+}
+
+static void mTXdiffMatrix (MTXdiff *mtx_diff_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_ptr = argv;
+ t_atom *list_out = mtx_diff_obj->list_out;
+ t_float *x = mtx_diff_obj->x;
+ t_float *y = mtx_diff_obj->y;
+ int count;
+
+ // size check
+ if (!size) {
+ post("mtx_diff: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_diff: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+ else if ((!x)||(!list_out)||(!y)) {
+ if (!x)
+ x = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!y)
+ y = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!list_out)
+ list_out = (t_atom *) getbytes (sizeof (t_atom) * (size+2));
+ }
+ else if (size != mtx_diff_obj->size) {
+ x = (t_float *) resizebytes (x,
+ sizeof (t_float) * (mtx_diff_obj->size),
+ sizeof (t_float) * (size));
+ y = (t_float *) resizebytes (y,
+ sizeof (t_float) * (mtx_diff_obj->size),
+ sizeof (t_float) * (size));
+ list_out = (t_atom *) resizebytes (list_out,
+ sizeof (t_atom) * (mtx_diff_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+ mtx_diff_obj->size = size;
+ mtx_diff_obj->rows = rows;
+ mtx_diff_obj->columns = columns;
+ mtx_diff_obj->list_out = list_out;
+ mtx_diff_obj->x = x;
+ mtx_diff_obj->y = y;
+
+ // main part
+ // reading matrix from inlet
+ if (mtx_diff_obj->diff_dimension == 2) {
+ readFloatFromListModulo (size, columns, list_ptr, x);
+ columns = mtx_diff_obj->rows;
+ rows = mtx_diff_obj->columns;
+ }
+ else
+ readFloatFromList (size, list_ptr, x);
+
+ // calculating diff
+ if (mtx_diff_obj->diff_direction == -1) {
+ x += columns-1;
+ y += columns-1;
+ for (count = rows; count--; x += columns, y += columns)
+ diffReverse (columns,x,y);
+ }
+ else
+ for (count = rows; count--; x += columns, y += columns)
+ diff (columns,x,y);
+ x = mtx_diff_obj->x;
+ y = mtx_diff_obj->y;
+
+ // writing matrix to outlet
+ if (mtx_diff_obj->diff_dimension == 2) {
+ columns = mtx_diff_obj->columns;
+ rows = mtx_diff_obj->rows;
+ writeFloatIntoListModulo (size, columns, list_out+2, y);
+ }
+ else
+ writeFloatIntoList (size, list_out+2, y);
+
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, rows);
+ SETFLOAT(&list_out[1], columns);
+ outlet_anything(mtx_diff_obj->list_outlet, gensym("matrix"),
+ mtx_diff_obj->size+2, list_out);
+}
+
+void mtx_diff_setup (void)
+{
+ mtx_diff_class = class_new
+ (gensym("mtx_diff"),
+ (t_newmethod) newMTXdiff,
+ (t_method) deleteMTXdiff,
+ sizeof (MTXdiff),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_diff_class, (t_method) mTXdiffBang);
+ class_addmethod (mtx_diff_class, (t_method) mTXdiffMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_diff_class, (t_method) mTXSetdiffDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_addmethod (mtx_diff_class, (t_method) mTXSetdiffDirection, gensym("direction"), A_DEFFLOAT,0);
+ class_sethelpsymbol (mtx_diff_class, gensym("iemmatrix/mtx_diff"));
+}
+
+void iemtx_diff_setup(void){
+ mtx_diff_setup();
+}
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();
+}
diff --git a/src/mtx_find.c b/src/mtx_find.c
new file mode 100644
index 0000000..6fdbee7
--- /dev/null
+++ b/src/mtx_find.c
@@ -0,0 +1,286 @@
+/*
+ * 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"
+
+static t_class *mtx_find_class;
+
+typedef struct _MTXfind_ MTXfind;
+struct _MTXfind_
+{
+ t_object x_obj;
+ int size;
+ int outsize;
+ int find_dimension;
+ int find_direction;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+};
+
+static void deleteMTXFind (MTXfind *mtx_find_obj)
+{
+ if (mtx_find_obj->list_out)
+ freebytes (mtx_find_obj->list_out, sizeof(t_atom)*(mtx_find_obj->size+2));
+}
+
+static void mTXSetFindDirection (MTXfind *mtx_find_obj, t_float c_dir)
+{
+ int direction = (int) c_dir;
+ if ((direction != -1) && (direction != 1))
+ direction = 1;
+ mtx_find_obj->find_direction = direction;
+}
+
+static void mTXSetFindDimension (MTXfind *mtx_find_obj, t_float c_dim)
+{
+ int dimension = (int) c_dim;
+ dimension = (dimension > 0)?dimension:0;
+ dimension = (dimension < 3)?dimension:3;
+ mtx_find_obj->find_dimension = dimension;
+}
+
+static void *newMTXFind (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXfind *mtx_find_obj = (MTXfind *) pd_new (mtx_find_class);
+ int c_dim = 0;
+ int c_dir = 1;
+
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mTXSetFindDimension (mtx_find_obj, (t_float) c_dim);
+ mTXSetFindDirection (mtx_find_obj, (t_float) c_dir);
+
+ mtx_find_obj->list_outlet = outlet_new (&mtx_find_obj->x_obj, gensym("matrix"));
+
+ error("[mtx_find]: this object is likely to change! not really for use yet");
+ return ((void *) mtx_find_obj);
+}
+
+static void mTXFindBang (MTXfind *mtx_find_obj)
+{
+ if (mtx_find_obj->list_out)
+ outlet_anything(mtx_find_obj->list_outlet, gensym("matrix"),
+ mtx_find_obj->outsize+2, mtx_find_obj->list_out);
+}
+/*
+static void copyList (int size, t_atom *x, t_atom *y)
+{
+ while(size--)
+ *y++=*x++;
+ }
+ */
+static int findPreviousNonZero (const int n, t_atom *x, int offset)
+{
+ x+=offset;
+ for (; offset > n; offset--, x--)
+ if (atom_getfloat(x))
+ return offset;
+ return -1;
+}
+static int findPreviousNonZeroStep (const int step, t_atom *x, int offset)
+{
+ x += offset;
+ for (; offset > 0; offset-=step, x-=step)
+ if (atom_getfloat(x))
+ return offset;
+ return -1;
+}
+static int findNextNonZero (const int n, t_atom *x, int offset)
+{
+ x+=offset;
+ for (; offset < n; offset++, x++)
+ if (atom_getfloat(x))
+ return offset;
+ return -1;
+}
+static int findNextNonZeroStep (const int n, const int step, t_atom *x, int offset)
+{
+ x += offset;
+ for (; offset < n; offset+=step, x+=step)
+ if (atom_getfloat(x))
+ return offset;
+ return -1;
+}
+
+static void findFirstNonZeroRow (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int offset;
+ int pos;
+ const int size = rows*columns;
+ for (offset = 0; offset < size; y++, offset+=columns) {
+ pos = findNextNonZero(offset+columns,x,offset)+1;
+ SETFLOAT(y,(t_float)pos);
+ }
+}
+static void findLastNonZeroRow (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int offset;
+ int pos;
+ const int size = rows*columns;
+ for (offset = columns-1; offset < size; y++, offset+=columns) {
+ pos = findPreviousNonZero(offset-columns,x,offset)+1;
+ SETFLOAT(y,(t_float)pos);
+ }
+}
+static void findFirstNonZeroColumn (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int offset;
+ int pos;
+ const int size = rows*columns;
+ for (offset = 0; offset < columns; y++, offset++) {
+ pos = findNextNonZeroStep(size,columns,x,offset)+1;
+ SETFLOAT(y,(t_float)pos);
+ }
+}
+static void findLastNonZeroColumn (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int offset;
+ int pos;
+ const int size = rows*columns;
+ for (offset = size-columns; offset < size; y++, offset++) {
+ pos = findPreviousNonZeroStep(columns,x,offset)+1;
+ SETFLOAT(y,(t_float)pos);
+ }
+}
+
+static int findAllNonZeros (int n, t_atom *x, t_atom *y)
+{
+ int outsize = 0;
+ int pos = 0;
+ while ((pos = findNextNonZero(n,x,pos)) != -1) {
+ pos++;
+ SETFLOAT(y,(t_float)pos);
+ y++;
+ outsize++;
+ }
+ return outsize;
+}
+
+static void zeroFloatList (int n, t_atom *x)
+{
+ for (;n--;x++)
+ SETFLOAT(x,0);
+}
+static void findReplaceNonZerosWithIndex (int n, t_atom *x, t_atom *y)
+{
+ int pos = 0;
+ zeroFloatList(n,y);
+ while ((pos = findNextNonZero(n,x,pos)) != -1) {
+ SETFLOAT(y+pos,(t_float)pos+1);
+ pos++;
+ }
+}
+
+static void mTXFindMatrix (MTXfind *mtx_find_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 = argv;
+ t_atom *list_out = mtx_find_obj->list_out;
+ int count;
+ int rows_out;
+ int columns_out;
+
+ // size check
+ if (!size) {
+ post("mtx_find: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_find: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size != mtx_find_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_find_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+
+ mtx_find_obj->size = size;
+ mtx_find_obj->list_out = list_out;
+
+ // main part
+ list_out += 2;
+ //copyList (size, argv, list_out);
+ rows_out = 1;
+ switch (mtx_find_obj->find_dimension) {
+ case 0:
+ columns_out = findAllNonZeros (size, list_in, list_out);
+ rows_out = 1;
+ break;
+ case 3:
+ findReplaceNonZerosWithIndex (size, list_in, list_out);
+ rows_out = rows;
+ columns_out = columns;
+ break;
+ case 2:
+ if (mtx_find_obj->find_direction == -1)
+ findLastNonZeroColumn (rows, columns, list_in, list_out);
+ else
+ findFirstNonZeroColumn (rows, columns, list_in, list_out);
+ columns_out = columns;
+ rows_out = 1;
+ break;
+ case 1:
+ if (mtx_find_obj->find_direction == -1)
+ findLastNonZeroRow (rows, columns, list_in, list_out);
+ else
+ findFirstNonZeroRow (rows, columns, list_in, list_out);
+ rows_out = rows;
+ columns_out = 1;
+ break;
+ }
+ mtx_find_obj->outsize = columns_out * rows_out;
+ list_out = mtx_find_obj->list_out;
+
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, rows_out);
+ SETFLOAT(&list_out[1], columns_out);
+ outlet_anything(mtx_find_obj->list_outlet, gensym("matrix"),
+ mtx_find_obj->outsize+2, list_out);
+}
+
+void mtx_find_setup (void)
+{
+ mtx_find_class = class_new
+ (gensym("mtx_find"),
+ (t_newmethod) newMTXFind,
+ (t_method) deleteMTXFind,
+ sizeof (MTXfind),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_find_class, (t_method) mTXFindBang);
+ class_addmethod (mtx_find_class, (t_method) mTXFindMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_find_class, (t_method) mTXSetFindDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_addmethod (mtx_find_class, (t_method) mTXSetFindDirection, gensym("direction"), A_DEFFLOAT,0);
+ class_sethelpsymbol (mtx_find_class, gensym("iemmatrix/mtx_find"));
+}
+
+void iemtx_find_setup(void){
+ mtx_find_setup();
+}
diff --git a/src/mtx_index.c b/src/mtx_index.c
new file mode 100644
index 0000000..1bf65ae
--- /dev/null
+++ b/src/mtx_index.c
@@ -0,0 +1,213 @@
+/*
+ * 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"
+
+static t_class *mtx_index_class;
+
+typedef struct _MTXindex_ MTXindex;
+struct _MTXindex_
+{
+ t_object x_obj;
+ int index_size;
+ int index_rows;
+ int index_columns;
+ t_float fill_value;
+ int max_index;
+ int *index_in;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+};
+
+static void deleteMTXIndex (MTXindex *mtx_index_obj)
+{
+ if (mtx_index_obj->index_in)
+ freebytes (mtx_index_obj->index_in, sizeof(int)*(mtx_index_obj->index_size+2));
+ if (mtx_index_obj->list_out)
+ freebytes (mtx_index_obj->list_out, sizeof(t_atom)*(mtx_index_obj->index_size+2));
+}
+
+static void *newMTXIndex (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXindex *mtx_index_obj = (MTXindex *) pd_new (mtx_index_class);
+ t_atom fill_atom;
+
+ SETFLOAT(&fill_atom,0);
+ switch ((argc>1)?1:argc) {
+ case 1:
+ fill_atom = *argv;
+ }
+ if (atom_getsymbol(&fill_atom) == gensym("nan"))
+ mtx_index_obj->fill_value = 0.0f/0.0f;
+ else
+ mtx_index_obj->fill_value = atom_getfloat(&fill_atom);
+
+ mtx_index_obj->list_outlet = outlet_new (&mtx_index_obj->x_obj, gensym("matrix"));
+ inlet_new(&mtx_index_obj->x_obj, &mtx_index_obj->x_obj.ob_pd, gensym("matrix"),gensym(""));
+
+ error("[mtx_index]: this object is likely to change! not really for use yet");
+
+ return ((void *) mtx_index_obj);
+}
+
+static void mTXIndexBang (MTXindex *mtx_index_obj)
+{
+ if (mtx_index_obj->list_out)
+ outlet_anything(mtx_index_obj->list_outlet, gensym("matrix"),
+ mtx_index_obj->index_size+2, mtx_index_obj->list_out);
+}
+/*
+ static void copyList (int size, t_atom *x, t_atom *y)
+ {
+ while(size--)
+ *y++=*x++;
+ }
+ */
+
+static int copyAtomToIntegerArrayMax (int n, t_atom *x, int *y)
+{
+ int max = atom_getint(x);
+ for (;n--;x++,y++) {
+ *y = atom_getint (x);
+ max = (*y > max)?*y:max;
+ }
+ return max;
+}
+
+static void setAtomListConstFloat (int n, t_atom *x, t_float f)
+{
+ for (;n--;x++)
+ SETFLOAT(x,f);
+}
+
+static void writeIndexedValuesIntoList (int n, int *index, t_atom *x, t_atom *y)
+{
+ for (;n--;index++,y++)
+ if (*index)
+ *y = x[*index-1];
+}
+
+static void mTXIndexRightMatrix (MTXindex *mtx_index_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 = argv;
+ t_atom *list_out = mtx_index_obj->list_out;
+ int *index_in = mtx_index_obj->index_in;
+ int max;
+
+ // size check
+ if (!size) {
+ post("mtx_index: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_index: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size != mtx_index_obj->index_size) {
+ if (!index_in)
+ index_in = (int *) getbytes (sizeof (int) * (size + 2));
+ else
+ index_in = (int *) resizebytes (index_in,
+ sizeof (int) * (mtx_index_obj->index_size+2),
+ sizeof (int) * (size + 2));
+ 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_index_obj->index_size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+
+ mtx_index_obj->index_size = size;
+ mtx_index_obj->index_columns = columns;
+ mtx_index_obj->index_rows = rows;
+ mtx_index_obj->list_out = list_out;
+ mtx_index_obj->index_in = index_in;
+
+ max = copyAtomToIntegerArrayMax (size, list_in, index_in);
+ mtx_index_obj->max_index = max;
+
+}
+
+static void mTXIndexMatrix (MTXindex *mtx_index_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 = argv;
+ t_atom *list_out = mtx_index_obj->list_out;
+ int count;
+ int index_rows = mtx_index_obj->index_rows;
+ int index_columns = mtx_index_obj->index_columns;
+ int *index = mtx_index_obj->index_in;
+
+ // size check
+ if (!size) {
+ post("mtx_index: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_index: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size < mtx_index_obj->max_index) {
+ post("mtx_index: index exceeds matrix dimensions");
+ return;
+ }
+ if ((!index)||(mtx_index_obj->index_size == 0)) {
+ post("mtx_index: index with what? no right matrix defined");
+ return;
+ }
+ // main part
+ list_out += 2;
+ setAtomListConstFloat (mtx_index_obj->index_size, list_out, mtx_index_obj->fill_value);
+ writeIndexedValuesIntoList (mtx_index_obj->index_size, index,list_in,list_out);
+ list_out = mtx_index_obj->list_out;
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, index_rows);
+ SETFLOAT(&list_out[1], index_columns);
+ outlet_anything(mtx_index_obj->list_outlet, gensym("matrix"),
+ mtx_index_obj->index_size+2, list_out);
+}
+
+void mtx_index_setup (void)
+{
+ mtx_index_class = class_new
+ (gensym("mtx_index"),
+ (t_newmethod) newMTXIndex,
+ (t_method) deleteMTXIndex,
+ sizeof (MTXindex),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_index_class, (t_method) mTXIndexBang);
+ class_addmethod (mtx_index_class, (t_method) mTXIndexMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_index_class, (t_method) mTXIndexRightMatrix, gensym(""), A_GIMME,0);
+ class_sethelpsymbol (mtx_index_class, gensym("iemmatrix/mtx_index"));
+}
+
+void iemtx_index_setup(void){
+ mtx_index_setup();
+}
diff --git a/src/mtx_minmax.c b/src/mtx_minmax.c
new file mode 100644
index 0000000..11f661f
--- /dev/null
+++ b/src/mtx_minmax.c
@@ -0,0 +1,284 @@
+/*
+ * 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"
+
+static t_class *mtx_minmax_class;
+
+typedef struct _MTXminmax_ MTXminmax;
+struct _MTXminmax_
+{
+ t_object x_obj;
+ int size;
+ int outsize;
+ int minmax_dimension;
+ int minmax_direction;
+ int operator_minimum; // 1 if we are [mtx_min], 0 if we are [mtx_max]
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+};
+
+static void deleteMTXMinMax (MTXminmax *mtx_minmax_obj)
+{
+ if (mtx_minmax_obj->list_out)
+ freebytes (mtx_minmax_obj->list_out, sizeof(t_atom)*(mtx_minmax_obj->size+2));
+}
+
+static void mTXSetMinMaxDirection (MTXminmax *mtx_minmax_obj, t_float c_dir)
+{
+ int direction = (int) c_dir;
+ if ((direction != -1) && (direction != 1))
+ direction = 1;
+ mtx_minmax_obj->minmax_direction = direction;
+}
+
+static void mTXSetMinMaxDimension (MTXminmax *mtx_minmax_obj, t_float c_dim)
+{
+ int dimension = (int) c_dim;
+ dimension = (dimension > 0)?dimension:0;
+ dimension = (dimension < 3)?dimension:3;
+ mtx_minmax_obj->minmax_dimension = dimension;
+}
+
+static void *newMTXMin (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXminmax *mtx_minmax_obj = (MTXminmax *) pd_new (mtx_minmax_class);
+ int c_dim = 1;
+ int c_dir = 1;
+
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mtx_minmax_obj->operator_minimum = 1;
+ mTXSetMinMaxDimension (mtx_minmax_obj, (t_float) c_dim);
+ mTXSetMinMaxDirection (mtx_minmax_obj, (t_float) c_dir);
+
+ mtx_minmax_obj->list_outlet = outlet_new (&mtx_minmax_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_minmax_obj);
+}
+static void *newMTXMax (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXminmax *mtx_minmax_obj = (MTXminmax *) pd_new (mtx_minmax_class);
+ int c_dim = 1;
+ int c_dir = 1;
+
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mtx_minmax_obj->operator_minimum = 0;
+ mTXSetMinMaxDimension (mtx_minmax_obj, (t_float) c_dim);
+ mTXSetMinMaxDirection (mtx_minmax_obj, (t_float) c_dir);
+
+ mtx_minmax_obj->list_outlet = outlet_new (&mtx_minmax_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_minmax_obj);
+}
+
+static void mTXMinMaxBang (MTXminmax *mtx_minmax_obj)
+{
+ if (mtx_minmax_obj->list_out)
+ outlet_anything(mtx_minmax_obj->list_outlet, gensym("matrix"),
+ mtx_minmax_obj->outsize+2, mtx_minmax_obj->list_out);
+}
+/*
+static void copyList (int size, t_atom *x, t_atom *y)
+{
+ while(size--)
+ *y++=*x++;
+ }
+ */
+
+static t_float minList (int n, t_atom *x)
+{
+ t_float min=atom_getfloat(x);
+ t_float f;
+ for (;n--;x++) {
+ f = atom_getfloat(x);
+ min = (min < f)?min:f;
+ }
+ return min;
+}
+
+static t_float minListStep (int n, const int step, t_atom *x)
+{
+ t_float min=atom_getfloat(x);
+ t_float f;
+ for (;n--;x+=step) {
+ f = atom_getfloat(x);
+ min = (min < f)?min:f;
+ }
+ return min;
+}
+
+static t_float maxList (int n, t_atom *x)
+{
+ t_float max=atom_getfloat(x);
+ t_float f;
+ for (;n--;x++) {
+ f = atom_getfloat(x);
+ max = (max > f)?max:f;
+ }
+ return max;
+}
+static t_float maxListStep (int n, const int step, t_atom *x)
+{
+ t_float max=atom_getfloat(x);
+ t_float f;
+ for (;n--;x+=step) {
+ f = atom_getfloat(x);
+ max = (max > f)?max:f;
+ }
+ return max;
+}
+
+static void minListColumns (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int count;
+ t_float f;
+ for (count=0; count < columns; count++, x++, y++) {
+ f=minListStep (rows, columns, x);
+ SETFLOAT(y,f);
+ }
+}
+static void minListRows (int rows, int columns, t_atom *x, t_atom *y)
+{
+ int count;
+ t_float f;
+ for (count=0; count < rows; count++, x+=columns, y++) {
+ f=minList (columns, x);
+ SETFLOAT(y,f);
+ }
+}
+static void maxListColumns (const int rows, const int columns, t_atom *x, t_atom *y)
+{
+ int count;
+ t_float f;
+ for (count=0; count < columns; count++, x++, y++) {
+ f=maxListStep (rows, columns, x);
+ SETFLOAT(y,f);
+ }
+}
+static void maxListRows (int rows, int columns, t_atom *x, t_atom *y)
+{
+ int count;
+ t_float f;
+ for (count=0; count < rows; count++, x+=columns, y++) {
+ f=maxList (columns, x);
+ SETFLOAT(y,f);
+ }
+}
+
+
+static void mTXMinMaxMatrix (MTXminmax *mtx_minmax_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 = argv;
+ t_atom *list_out = mtx_minmax_obj->list_out;
+ int count;
+ int rows_out;
+ int columns_out;
+
+ // size check
+ if (!size) {
+ post("mtx_minmax: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_minmax: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size != mtx_minmax_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_minmax_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+
+ mtx_minmax_obj->size = size;
+ mtx_minmax_obj->list_out = list_out;
+
+ // main part
+ list_out += 2;
+ //copyList (size, argv, list_out);
+ switch (mtx_minmax_obj->minmax_dimension) {
+ case 0:
+ columns_out = 1;
+ rows_out = 1;
+ if (mtx_minmax_obj->operator_minimum)
+ minListRows (1, size, list_in, list_out);
+ else
+ maxListRows (1, size, list_in, list_out);
+ break;
+ case 1:
+ rows_out = rows;
+ columns_out = 1;
+ if (mtx_minmax_obj->operator_minimum)
+ minListRows (rows, columns, list_in, list_out);
+ else
+ maxListRows (rows, columns, list_in, list_out);
+ break;
+ case 2:
+ rows_out = 1;
+ columns_out = columns;
+ if (mtx_minmax_obj->operator_minimum)
+ minListColumns (rows, columns, list_in, list_out);
+ else
+ maxListColumns (rows, columns, list_in, list_out);
+ break;
+ }
+ mtx_minmax_obj->outsize = columns_out * rows_out;
+ list_out = mtx_minmax_obj->list_out;
+
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, rows_out);
+ SETFLOAT(&list_out[1], columns_out);
+ outlet_anything(mtx_minmax_obj->list_outlet, gensym("matrix"),
+ mtx_minmax_obj->outsize+2, list_out);
+}
+
+void mtx_minmax_setup (void)
+{
+ mtx_minmax_class = class_new
+ (gensym("mtx_min"),
+ (t_newmethod) newMTXMin,
+ (t_method) deleteMTXMinMax,
+ sizeof (MTXminmax),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_minmax_class, (t_method) mTXMinMaxBang);
+ class_addmethod (mtx_minmax_class, (t_method) mTXMinMaxMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_minmax_class, (t_method) mTXSetMinMaxDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_addmethod (mtx_minmax_class, (t_method) mTXSetMinMaxDirection, gensym("direction"), A_DEFFLOAT,0);
+ class_addcreator ((t_newmethod) newMTXMax, gensym("mtx_max"), A_GIMME,0);
+ class_sethelpsymbol (mtx_minmax_class, gensym("iemmatrix/mtx_minmax"));
+}
+
+void iemtx_minmax_setup(void){
+ mtx_minmax_setup();
+}
diff --git a/src/mtx_not.c b/src/mtx_not.c
new file mode 100644
index 0000000..e73307a
--- /dev/null
+++ b/src/mtx_not.c
@@ -0,0 +1,88 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * Copyright (c) IOhannes m zmölnig, forum::für::umläute
+ * 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"
+
+/* mtx_not: B=!A; */
+
+#define MTX_ALMOSTZERO 1e-19
+
+static t_class *mtx_not_class;
+
+static void mtx_not_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *m;
+ int n = argc-2;
+
+ if (argc<2){ post("mtx_!: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_!: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ t_float f = atom_getfloat(argv++);
+ SETFLOAT(m, (t_float)(f<MTX_ALMOSTZERO&&f>-MTX_ALMOSTZERO));
+ m++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+
+static void mtx_not_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc;
+ t_atom *m;
+ t_float factor = x->f;
+
+ adjustsize(&x->m, 1, argc);
+ m = x->m.atombuffer;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ t_float f = atom_getfloat(argv++);
+ (m++)->a_w.w_float = (t_float)(f<MTX_ALMOSTZERO&&f>-MTX_ALMOSTZERO);
+ }
+
+ outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer);
+}
+
+static void *mtx_not_new(t_symbol *s)
+{
+ /* element not */
+ t_matrix *x = (t_matrix *)pd_new(mtx_not_class);
+ outlet_new(&x->x_obj, 0);
+ x->col = x->row = 0;
+ x->atombuffer = 0;
+ return(x);
+}
+
+void mtx_not_setup(void)
+{
+ mtx_not_class = class_new(gensym("mtx_not"), (t_newmethod)mtx_not_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)mtx_not_new, gensym("mtx_!"), A_GIMME,0);
+ class_addmethod(mtx_not_class, (t_method)mtx_not_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_not_class, mtx_not_list);
+ class_addbang (mtx_not_class, mtx_binmtx_bang);
+
+ class_sethelpsymbol(mtx_not_class, gensym("iemmatrix/mtx_not"));
+}
+
+void iemtx_not_setup(void)
+{
+ mtx_not_setup();
+}
diff --git a/src/mtx_repmat.c b/src/mtx_repmat.c
new file mode 100644
index 0000000..3ab686f
--- /dev/null
+++ b/src/mtx_repmat.c
@@ -0,0 +1,161 @@
+/*
+ * 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"
+
+static t_class *mtx_repmat_class;
+
+typedef struct _MTXrepmat_ MTXrepmat;
+struct _MTXrepmat_
+{
+ t_object x_obj;
+ int size;
+ int repeat_rows;
+ int repeat_cols;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+};
+
+static void deleteMTXRepmat (MTXrepmat *mtx_repmat_obj)
+{
+ if (mtx_repmat_obj->list_out)
+ freebytes (mtx_repmat_obj->list_out, sizeof(t_atom)*(mtx_repmat_obj->size+2));
+}
+static void mTXRepmatList (MTXrepmat *mtx_repmat_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ if (argc!=2) {
+ post("mtx_repmat: there have to be exactly 2 arguments");
+ return;
+ }
+ mtx_repmat_obj->repeat_rows = atom_getint(argv++);
+ mtx_repmat_obj->repeat_cols = atom_getint(argv);
+}
+
+
+static void *newMTXRepmat (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXrepmat *mtx_repmat_obj = (MTXrepmat *) pd_new (mtx_repmat_class);
+ mtx_repmat_obj->repeat_cols = 1;
+ mtx_repmat_obj->repeat_rows = 1;
+
+ if (argc)
+ mTXRepmatList (mtx_repmat_obj, gensym("list"), argc, argv);
+
+ mtx_repmat_obj->list_outlet = outlet_new (&mtx_repmat_obj->x_obj, gensym("matrix"));
+ inlet_new(&mtx_repmat_obj->x_obj, &mtx_repmat_obj->x_obj.ob_pd, gensym("list"),gensym(""));
+ return ((void *) mtx_repmat_obj);
+}
+
+static void mTXRepmatBang (MTXrepmat *mtx_repmat_obj)
+{
+ if (mtx_repmat_obj->list_out)
+ outlet_anything(mtx_repmat_obj->list_outlet, gensym("matrix"),
+ mtx_repmat_obj->size+2, mtx_repmat_obj->list_out);
+}
+
+static void copyList (int n, t_atom *x, t_atom *y)
+{
+ while (n--)
+ *y++=*x++;
+}
+
+static void writeRepeatIntoMatrix (int repeat_rows, int repeat_cols, int rows, int columns, t_atom *x, t_atom *y)
+{
+ int row_cnt;
+ int col_cnt;
+ int idx = 0;
+ int new_col = columns * repeat_cols;
+ t_atom *ptr = y;
+
+ // writing each row repeatedly (repeat_col times) into output array
+ // so that : row1#1 row1#2 ... row1#RN | ... | rowN#1 rowN#2 ... rowN#RN
+ for (row_cnt=rows;row_cnt--;x+=columns)
+ for(col_cnt=repeat_cols;col_cnt--;ptr+=columns)
+ copyList (columns, x, ptr);
+
+ // repeating the above written long lines repeat row_repeat times in output array
+ for (;--repeat_rows;)
+ for (row_cnt=rows;row_cnt--;y+=new_col,ptr+=new_col)
+ copyList (new_col, y, ptr);
+
+}
+static void mTXRepmatMatrix (MTXrepmat *mtx_repmat_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ int rows = atom_getint (argv++);
+ int columns = atom_getint (argv++);
+ int rep_rows = mtx_repmat_obj->repeat_rows;
+ int rep_cols = mtx_repmat_obj->repeat_cols;
+ int mrows = rows * rep_rows;
+ int mcolumns = columns * rep_cols;
+ int size = rows * columns;
+ int list_size = argc - 2;
+ t_atom *list_in = argv;
+ t_atom *list_out = mtx_repmat_obj->list_out;
+
+ // size check
+ if (!size) {
+ post("mtx_repmat: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_repmat: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ mrows = rows * rep_rows;
+ mcolumns = columns * rep_cols;
+ size = mrows * mcolumns;
+
+ if (size != mtx_repmat_obj->size) {
+ if (list_out)
+ list_out = (t_atom*) resizebytes (list_out,
+ sizeof(t_atom)*(mtx_repmat_obj->size+2),
+ sizeof(t_atom)*(size+2));
+ else
+ list_out = (t_atom*) getbytes (sizeof(t_atom)*(size+2));
+ mtx_repmat_obj->list_out = list_out;
+ mtx_repmat_obj->size = size;
+ //post("size %d, rows %d, columns %d", size, rows, columns);
+ }
+ // main part
+
+ writeRepeatIntoMatrix (rep_rows, rep_cols, rows, columns,
+ list_in, list_out+2);
+ SETFLOAT(list_out, mrows);
+ SETFLOAT(&list_out[1], mcolumns);
+
+ mTXRepmatBang (mtx_repmat_obj);
+}
+
+void mtx_repmat_setup (void)
+{
+ mtx_repmat_class = class_new
+ (gensym("mtx_repmat"),
+ (t_newmethod) newMTXRepmat,
+ (t_method) deleteMTXRepmat,
+ sizeof (MTXrepmat),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_repmat_class, (t_method) mTXRepmatBang);
+ class_addmethod (mtx_repmat_class, (t_method) mTXRepmatMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_repmat_class, (t_method) mTXRepmatList, gensym(""), A_GIMME,0);
+ class_sethelpsymbol (mtx_repmat_class, gensym("iemmatrix/mtx_repmat"));
+}
+
+void iemtx_repmat_setup(void){
+ mtx_repmat_setup();
+}
diff --git a/src/mtx_reverse.c b/src/mtx_reverse.c
new file mode 100644
index 0000000..b95d23d
--- /dev/null
+++ b/src/mtx_reverse.c
@@ -0,0 +1,176 @@
+/*
+ * 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"
+
+static t_class *mtx_reverse_class;
+
+typedef struct _MTXreverse_ MTXreverse;
+struct _MTXreverse_
+{
+ t_object x_obj;
+ int size;
+ int reverse_dimension;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+ t_atom *list_in;
+};
+
+static void deleteMTXreverse (MTXreverse *mtx_reverse_obj)
+{
+ if (mtx_reverse_obj->list_out)
+ freebytes (mtx_reverse_obj->list_out, sizeof(t_atom)*(mtx_reverse_obj->size+2));
+}
+
+static void mTXSetreverseDimension (MTXreverse *mtx_reverse_obj, t_float c_dim)
+{
+ int dimension = (int) c_dim;
+ dimension = (dimension > 0)?dimension:0;
+ dimension = (dimension < 2)?dimension:2;
+ mtx_reverse_obj->reverse_dimension = dimension;
+}
+
+static void *newMTXreverse (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXreverse *mtx_reverse_obj = (MTXreverse *) pd_new (mtx_reverse_class);
+ int c_dim = 0;
+
+ mtx_reverse_obj->reverse_dimension = c_dim;
+ switch ((argc>1)?1:argc) {
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mTXSetreverseDimension (mtx_reverse_obj, (t_float) c_dim);
+
+ mtx_reverse_obj->list_outlet = outlet_new (&mtx_reverse_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_reverse_obj);
+}
+
+static void mTXreverseBang (MTXreverse *mtx_reverse_obj)
+{
+ if (mtx_reverse_obj->list_out)
+ outlet_anything(mtx_reverse_obj->list_outlet, gensym("matrix"),
+ mtx_reverse_obj->size+2, mtx_reverse_obj->list_out);
+}
+
+static void copyList (int n, t_atom *x, t_atom *y)
+{
+ for (;n--;)
+ *y++ = *x++;
+}
+static void reverseList (int n, t_atom *y)
+{
+ t_atom *read = y;
+ t_atom tmp;
+ y += n-1;
+ n >>= 1;
+ for (;n--;) {
+ tmp = *y;
+ *y-- = *read;
+ *read++ = tmp;
+ }
+}
+static void reverseListStep (int n, int step, t_atom *y)
+{
+ t_atom *read = y;
+ t_atom tmp;
+ n /= step;
+ y += (n-1) * step;
+ n >>= 1;
+ for (;n--; y-=step, read+=step) {
+ tmp = *y;
+ *y = *read;
+ *read = tmp;
+ }
+}
+
+static void mTXreverseMatrix (MTXreverse *mtx_reverse_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 = argv;
+ t_atom *list_out = mtx_reverse_obj->list_out;
+ int count;
+
+ // size check
+ if (!size) {
+ post("mtx_reverse: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_reverse: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+
+ if (size != mtx_reverse_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_reverse_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+
+ mtx_reverse_obj->size = size;
+ mtx_reverse_obj->list_out = list_out;
+
+ // main part
+ list_out += 2;
+ copyList (size, argv, list_out);
+ switch (mtx_reverse_obj->reverse_dimension) {
+ case 2:
+ for (count = columns; count--; list_out++)
+ reverseListStep (size, columns, list_out);
+ break;
+ case 1:
+ for (count = rows; count--; list_out += columns)
+ reverseList (columns, list_out);
+ break;
+ case 0:
+ reverseList (size, list_out);
+ break;
+ }
+ list_out = mtx_reverse_obj->list_out;
+
+
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, rows);
+ SETFLOAT(&list_out[1], columns);
+ outlet_anything(mtx_reverse_obj->list_outlet, gensym("matrix"),
+ mtx_reverse_obj->size+2, list_out);
+}
+
+void mtx_reverse_setup (void)
+{
+ mtx_reverse_class = class_new
+ (gensym("mtx_reverse"),
+ (t_newmethod) newMTXreverse,
+ (t_method) deleteMTXreverse,
+ sizeof (MTXreverse),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_reverse_class, (t_method) mTXreverseBang);
+ class_addmethod (mtx_reverse_class, (t_method) mTXreverseMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_reverse_class, (t_method) mTXSetreverseDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_sethelpsymbol (mtx_reverse_class, gensym("iemmatrix/mtx_reverse"));
+}
+
+void iemtx_reverse_setup(void){
+ mtx_reverse_setup();
+}
diff --git a/src/mtx_sort.c b/src/mtx_sort.c
new file mode 100644
index 0000000..fb47ed6
--- /dev/null
+++ b/src/mtx_sort.c
@@ -0,0 +1,325 @@
+/*
+ * 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"
+
+static t_class *mtx_sort_class;
+
+typedef struct _MTXSort_ MTXSort;
+struct _MTXSort_
+{
+ t_object x_obj;
+ int rows;
+ int columns;
+ int size;
+ int sort_dimension;
+ int sort_direction;
+
+ t_outlet *list_outlet1;
+ t_outlet *list_outlet2;
+
+ t_atom *list_out1;
+ t_atom *list_out2;
+ t_atom *list_in;
+ t_float *x;
+// t_float *y;
+ t_float *i;
+};
+
+static void deleteMTXSort (MTXSort *mtx_sort_obj)
+{
+ if (mtx_sort_obj->list_out1)
+ freebytes (mtx_sort_obj->list_out1, sizeof(t_atom)*(mtx_sort_obj->size+2));
+ if (mtx_sort_obj->list_out2)
+ freebytes (mtx_sort_obj->list_out2, sizeof(t_atom)*(mtx_sort_obj->size+2));
+ if (mtx_sort_obj->x)
+ freebytes (mtx_sort_obj->x, sizeof(t_float)*(mtx_sort_obj->size));
+ //if (mtx_sort_obj->y)
+ // freebytes (mtx_sort_obj->y, sizeof(t_float)*(mtx_sort_obj->size));
+ if (mtx_sort_obj->i)
+ freebytes (mtx_sort_obj->i, sizeof(t_float)*(mtx_sort_obj->size));
+}
+
+static void mTXSetSortDirection (MTXSort *mtx_sort_obj, t_float s_dir)
+{
+ int direction = (int) s_dir;
+ mtx_sort_obj->sort_direction = (direction==-1)?direction:1;
+}
+static void mTXSetSortDimension (MTXSort *mtx_sort_obj, t_float s_dim)
+{
+ int dimension = (int) s_dim;
+ dimension = (dimension<2)?dimension:2;
+ dimension = (dimension>0)?dimension:0;
+ mtx_sort_obj->sort_dimension = dimension;
+}
+
+static void *newMTXSort (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXSort *mtx_sort_obj = (MTXSort *) pd_new (mtx_sort_class);
+ int c_dir = 1;
+ int c_dim = 1;
+
+ mtx_sort_obj->sort_dimension = c_dim;
+ switch ((argc>2)?2:argc) {
+ case 2:
+ c_dir = atom_getint(argv+1);
+ case 1:
+ c_dim = atom_getint(argv);
+ }
+ mTXSetSortDirection (mtx_sort_obj, (t_float) c_dir);
+ mTXSetSortDimension (mtx_sort_obj, (t_float) c_dim);
+
+ mtx_sort_obj->list_outlet1 = outlet_new (&mtx_sort_obj->x_obj, gensym("matrix"));
+ mtx_sort_obj->list_outlet2 = outlet_new (&mtx_sort_obj->x_obj, gensym("matrix"));
+ return ((void *) mtx_sort_obj);
+}
+
+static void mTXSortBang (MTXSort *mtx_sort_obj)
+{
+ if (mtx_sort_obj->list_out1)
+ outlet_anything(mtx_sort_obj->list_outlet1, gensym("matrix"),
+ mtx_sort_obj->size+2, mtx_sort_obj->list_out1);
+ if (mtx_sort_obj->list_out2)
+ outlet_anything(mtx_sort_obj->list_outlet2, gensym("matrix"),
+ mtx_sort_obj->size+2, mtx_sort_obj->list_out2);
+}
+
+static void writeFloatIntoList (int n, t_atom *l, t_float *f)
+{
+ for (;n--;f++, l++)
+ SETFLOAT (l, *f);
+}
+static void readFloatFromList (int n, t_atom *l, t_float *f)
+{
+ while (n--)
+ *f++ = atom_getfloat (l++);
+}
+static void readFloatFromListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ *f = atom_getfloat (ptr);
+}
+static void writeFloatIntoListModulo (int n, int m, t_atom *l, t_float *f)
+{
+ t_atom *ptr = l;
+ int count1, count2;
+ n /= m;
+ count1 = m;
+ while (count1--)
+ for (count2 = n, ptr = l++; count2--; ptr += m, f++)
+ SETFLOAT(ptr,*f);
+}
+static void sortVector (int n, t_float *x, t_float *i, int direction)
+{
+ int step = n;
+ int size = n;
+ int k, loops = 1;
+ int i_tmp;
+ t_float x_tmp;
+
+ switch (direction) {
+ case -1:
+ while (step > 1) {
+ step = (step % 2)?(step+1)/2:step/2;
+ k = loops;
+ loops += 2;
+ while(k--) { /* there might be some optimization in here */
+ for (n=0; n<(size-step); n++)
+ if (x[n] < x[n+step]) {
+ i_tmp = i[n];
+ x_tmp = x[n];
+ x[n] = x[n+step];
+ x[n+step] = x_tmp;
+ i[n] = i[n+step];
+ i[n+step] = i_tmp;
+ }
+ }
+ }
+ break;
+ default:
+ case 1:
+ while (step > 1) {
+ step = (step % 2)?(step+1)/2:step/2;
+ k = loops;
+ loops += 2;
+ while(k--) { /* there might be some optimization in here */
+ for (n=0; n<(size-step); n++)
+ if (x[n] > x[n+step]) {
+ i_tmp = i[n];
+ x_tmp = x[n];
+ x[n] = x[n+step];
+ x[n+step] = x_tmp;
+ i[n] = i[n+step];
+ i[n+step] = i_tmp;
+ }
+ }
+ }
+ }
+}
+
+static void indexingVector (int n, int m, int dimension, t_float *i)
+{
+ int count;
+ int count2;
+ int idx = n;
+ t_float *ptr;
+ i += n;
+ switch (dimension) {
+ case 2:
+ n /= m;
+ for (count = m; count--;) {
+ ptr = --i;
+ for (count2 = n; count2--; ptr -= m)
+ *ptr = idx--;
+ }
+ break;
+ default:
+ case 1:
+ for (; idx;)
+ *--i = idx--;
+ }
+}
+
+static void mTXSortMatrix (MTXSort *mtx_sort_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_ptr = argv;
+ t_atom *list_out1 = mtx_sort_obj->list_out1;
+ t_atom *list_out2 = mtx_sort_obj->list_out2;
+ t_float *x = mtx_sort_obj->x;
+ //t_float *y = mtx_sort_obj->y;
+ t_float *i = mtx_sort_obj->i;
+ int count;
+
+ // size check
+ if (!size) {
+ post("mtx_sort: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_sort: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+ else if ((!x)||(!list_out1)||(!list_out2)/*||(!y)*/) {
+ if (!x)
+ x = (t_float *) getbytes (sizeof (t_float) * (size));
+ //if (!y)
+ // y = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!i)
+ i = (t_float *) getbytes (sizeof (t_float) * (size));
+ if (!list_out1)
+ list_out1 = (t_atom *) getbytes (sizeof (t_atom) * (size+2));
+ if (!list_out2)
+ list_out2 = (t_atom *) getbytes (sizeof (t_atom) * (size+2));
+ }
+ else if (size != mtx_sort_obj->size) {
+ x = (t_float *) resizebytes (x,
+ sizeof (t_float) * (mtx_sort_obj->size),
+ sizeof (t_float) * (size));
+ //y = (t_float *) resizebytes (y,
+ // sizeof (t_float) * (mtx_sort_obj->size),
+ // sizeof (t_float) * (size));
+ i = (t_float *) resizebytes (i,
+ sizeof (t_float) * (mtx_sort_obj->size),
+ sizeof (t_float) * (size));
+ list_out1 = (t_atom *) resizebytes (list_out1,
+ sizeof (t_atom) * (mtx_sort_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ list_out2 = (t_atom *) resizebytes (list_out2,
+ sizeof (t_atom) * (mtx_sort_obj->size+2),
+ sizeof (t_atom) * (size + 2));
+ }
+
+ mtx_sort_obj->list_out1 = list_out1;
+ mtx_sort_obj->list_out2 = list_out2;
+ mtx_sort_obj->x = x;
+ // mtx_sort_obj->y = y;
+ mtx_sort_obj->i = i;
+ mtx_sort_obj->size = size;
+ mtx_sort_obj->rows = rows;
+ mtx_sort_obj->columns = columns;
+
+ // generating indexing vector
+ indexingVector (size, columns, mtx_sort_obj->sort_dimension, i);
+
+ // main part
+ // reading matrix from inlet
+ if (mtx_sort_obj->sort_dimension == 2) {
+ readFloatFromListModulo (size, columns, list_ptr, x);
+ columns = mtx_sort_obj->rows;
+ rows = mtx_sort_obj->columns;
+ }
+ else
+ readFloatFromList (size, list_ptr, x);
+
+ // calculating sort
+ if (mtx_sort_obj->sort_dimension == 0)
+ sortVector (size,x,i,mtx_sort_obj->sort_direction);
+ else
+ for (count = rows; count--;x+=columns,i+=columns)
+ sortVector (columns,x,i,mtx_sort_obj->sort_direction);
+ x = mtx_sort_obj->x;
+ i = mtx_sort_obj->i;
+
+ // writing matrix to outlet
+ if (mtx_sort_obj->sort_dimension == 2) {
+ columns = mtx_sort_obj->columns;
+ rows = mtx_sort_obj->rows;
+ writeFloatIntoListModulo (size, columns, list_out1+2, x);
+ writeFloatIntoListModulo (size, columns, list_out2+2, i);
+ }
+ else {
+ writeFloatIntoList (size, list_out1+2, x);
+ writeFloatIntoList (size, list_out2+2, i);
+ }
+
+ SETSYMBOL(list_out1, gensym("matrix"));
+ SETFLOAT(list_out1, rows);
+ SETFLOAT(&list_out1[1], columns);
+ outlet_anything(mtx_sort_obj->list_outlet1, gensym("matrix"),
+ mtx_sort_obj->size+2, list_out1);
+ SETSYMBOL(list_out2, gensym("matrix"));
+ SETFLOAT(list_out2, rows);
+ SETFLOAT(&list_out2[1], columns);
+ outlet_anything(mtx_sort_obj->list_outlet2, gensym("matrix"),
+ mtx_sort_obj->size+2, list_out2);
+}
+
+void mtx_sort_setup (void)
+{
+ mtx_sort_class = class_new
+ (gensym("mtx_sort"),
+ (t_newmethod) newMTXSort,
+ (t_method) deleteMTXSort,
+ sizeof (MTXSort),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_sort_class, (t_method) mTXSortBang);
+ class_addmethod (mtx_sort_class, (t_method) mTXSortMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_sort_class, (t_method) mTXSetSortDimension, gensym("dimension"), A_DEFFLOAT,0);
+ class_addmethod (mtx_sort_class, (t_method) mTXSetSortDirection, gensym("direction"), A_DEFFLOAT,0);
+ class_sethelpsymbol (mtx_sort_class, gensym("iemmatrix/mtx_sort"));
+}
+
+void iemtx_sort_setup(void){
+ mtx_sort_setup();
+}