diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-09-19 14:47:50 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-09-19 14:47:50 +0000 |
commit | 208200ef713d588a1cb5c4d125b2bfccc9a7e2ce (patch) | |
tree | 29a88daf24459282860deb1b7bb684c5eaf49103 /src | |
parent | 38ee08dc2ce882e4fa8266f0d07fae258d098991 (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.c | 12 | ||||
-rw-r--r-- | src/iemmatrix_sources.h | 12 | ||||
-rw-r--r-- | src/mtx_colon.c | 114 | ||||
-rw-r--r-- | src/mtx_conv.c | 337 | ||||
-rw-r--r-- | src/mtx_cumsum.c | 238 | ||||
-rw-r--r-- | src/mtx_diff.c | 232 | ||||
-rw-r--r-- | src/mtx_fill.c | 356 | ||||
-rw-r--r-- | src/mtx_find.c | 286 | ||||
-rw-r--r-- | src/mtx_index.c | 213 | ||||
-rw-r--r-- | src/mtx_minmax.c | 284 | ||||
-rw-r--r-- | src/mtx_not.c | 88 | ||||
-rw-r--r-- | src/mtx_repmat.c | 161 | ||||
-rw-r--r-- | src/mtx_reverse.c | 176 | ||||
-rw-r--r-- | src/mtx_sort.c | 325 |
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(); +} |