From 208200ef713d588a1cb5c4d125b2bfccc9a7e2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 19 Sep 2005 14:47:50 +0000 Subject: added a bunch of new objects (from f.zotter); some of them are unstable, some are likely to change in their behaviour (read: not yet for use) svn path=/trunk/externals/iem/iemmatrix/; revision=3598 --- src/mtx_conv.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 src/mtx_conv.c (limited to 'src/mtx_conv.c') 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_sizerows != 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(); +} -- cgit v1.2.1