diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-09-20 08:12:38 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-09-20 08:12:38 +0000 |
commit | 59a57d6fd293f9ff9bfe86cf2da90a890495c16b (patch) | |
tree | a52e24b949fbc1f45968c6a8fdc2b8887ac9bdf4 | |
parent | 208200ef713d588a1cb5c4d125b2bfccc9a7e2ce (diff) |
added more objects by fz
svn path=/trunk/externals/iem/iemmatrix/; revision=3600
-rw-r--r-- | src/mtx_decay.c | 251 | ||||
-rw-r--r-- | src/mtx_rowrfft.c | 205 | ||||
-rw-r--r-- | src/mtx_rowrifft.c | 238 | ||||
-rw-r--r-- | src/mtx_slice.c | 215 |
4 files changed, 909 insertions, 0 deletions
diff --git a/src/mtx_decay.c b/src/mtx_decay.c new file mode 100644 index 0000000..9170d43 --- /dev/null +++ b/src/mtx_decay.c @@ -0,0 +1,251 @@ +/* + * 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_decay_class; + +typedef struct _MTXDecay_ MTXDecay; +struct _MTXDecay_ +{ + t_object x_obj; + int rows; + int columns; + int size; + int decay_dimension; + int decay_direction; + t_float decay_parameter; + + t_outlet *list_outlet; + + t_atom *list_out; + t_atom *list_in; + t_float *x; + t_float *y; +}; + +static void deleteMTXDecay (MTXDecay *mtx_decay_obj) +{ + if (mtx_decay_obj->list_out) + freebytes (mtx_decay_obj->list_out, sizeof(t_atom)*(mtx_decay_obj->size+2)); + if (mtx_decay_obj->x) + freebytes (mtx_decay_obj->x, sizeof(t_float)*(mtx_decay_obj->size)); + if (mtx_decay_obj->y) + freebytes (mtx_decay_obj->y, sizeof(t_float)*(mtx_decay_obj->size)); +} + +static void mTXSetDecayParameter (MTXDecay *mtx_decay_obj, t_float d_param) +{ + d_param = (d_param > 0.0f)?d_param:0.0f; + d_param = (d_param < 1.0f)?d_param:1.0f; + mtx_decay_obj->decay_parameter = d_param; +} +static void mTXSetDecayDirection (MTXDecay *mtx_decay_obj, t_float c_dir) +{ + int direction = (int) c_dir; + mtx_decay_obj->decay_direction = (direction==-1)?direction:1; +} +static void mTXSetDecayDimension (MTXDecay *mtx_decay_obj, t_float c_dim) +{ + int dimension = (int) c_dim; + mtx_decay_obj->decay_dimension = (dimension==2)?dimension:1; +} + +static void *newMTXDecay (t_symbol *s, int argc, t_atom *argv) +{ + MTXDecay *mtx_decay_obj = (MTXDecay *) pd_new (mtx_decay_class); + int c_dir = 1; + int c_dim = 1; + t_float c_par = 0.9f; + + mtx_decay_obj->decay_dimension = c_dim; + switch ((argc>3)?3:argc) { + case 3: + c_dir = atom_getint(argv+2); + case 2: + c_dim = atom_getint(argv+1); + case 1: + c_par = atom_getfloat(argv); + } + mTXSetDecayParameter (mtx_decay_obj, c_par); + mTXSetDecayDirection (mtx_decay_obj, (t_float) c_dir); + mTXSetDecayDimension (mtx_decay_obj, (t_float) c_dim); + + mtx_decay_obj->list_outlet = outlet_new (&mtx_decay_obj->x_obj, gensym("matrix")); + return ((void *) mtx_decay_obj); +} + +static void mTXDecayBang (MTXDecay *mtx_decay_obj) +{ + if (mtx_decay_obj->list_out) + outlet_anything(mtx_decay_obj->list_outlet, gensym("matrix"), + mtx_decay_obj->size+2, mtx_decay_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 deCay (int n, t_float *x, t_float *y, t_float alpha) +{ + t_float decay = *x; + t_float oneminusalpha = 1.0f-alpha; + for (;n--; x++, y++) { + decay = alpha * decay + oneminusalpha * *x; + *y = decay = (decay < *x)? *x : decay; + } +} +static void deCayReverse (int n, t_float *x, t_float *y, t_float alpha) +{ + t_float decay = *x; + t_float oneminusalpha = 1.0f-alpha; + for (;n--; x--, y--) { + decay = alpha * decay + oneminusalpha * *x; + *y = decay = (decay < *x)? *x : decay; + } +} + +static void mTXDecayMatrix (MTXDecay *mtx_decay_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_decay_obj->list_out; + t_float *x = mtx_decay_obj->x; + t_float *y = mtx_decay_obj->y; + int count; + + // size check + if (!size) { + post("mtx_decay: invalid dimensions"); + return; + } + else if (list_size<size) { + post("mtx_decay: 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_decay_obj->size) { + x = (t_float *) resizebytes (x, + sizeof (t_float) * (mtx_decay_obj->size), + sizeof (t_float) * (size)); + y = (t_float *) resizebytes (y, + sizeof (t_float) * (mtx_decay_obj->size), + sizeof (t_float) * (size)); + list_out = (t_atom *) resizebytes (list_out, + sizeof (t_atom) * (mtx_decay_obj->size+2), + sizeof (t_atom) * (size + 2)); + } + mtx_decay_obj->size = size; + mtx_decay_obj->rows = rows; + mtx_decay_obj->columns = columns; + mtx_decay_obj->list_out = list_out; + mtx_decay_obj->x = x; + mtx_decay_obj->y = y; + + // main part + // reading matrix from inlet + if (mtx_decay_obj->decay_dimension == 2) { + readFloatFromListModulo (size, columns, list_ptr, x); + columns = mtx_decay_obj->rows; + rows = mtx_decay_obj->columns; + } + else + readFloatFromList (size, list_ptr, x); + + // calculating decay + if (mtx_decay_obj->decay_direction == -1) { + x += columns-1; + y += columns-1; + for (count = rows; count--; x += columns, y += columns) + deCayReverse (columns,x,y,mtx_decay_obj->decay_parameter); + } + else + for (count = rows; count--; x += columns, y += columns) + deCay (columns,x,y,mtx_decay_obj->decay_parameter); + x = mtx_decay_obj->x; + y = mtx_decay_obj->y; + + // writing matrix to outlet + if (mtx_decay_obj->decay_dimension == 2) { + columns = mtx_decay_obj->columns; + rows = mtx_decay_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_decay_obj->list_outlet, gensym("matrix"), + mtx_decay_obj->size+2, list_out); +} + +void mtx_decay_setup (void) +{ + mtx_decay_class = class_new + (gensym("mtx_decay"), + (t_newmethod) newMTXDecay, + (t_method) deleteMTXDecay, + sizeof (MTXDecay), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (mtx_decay_class, (t_method) mTXDecayBang); + class_addmethod (mtx_decay_class, (t_method) mTXDecayMatrix, gensym("matrix"), A_GIMME,0); + class_addmethod (mtx_decay_class, (t_method) mTXSetDecayParameter, gensym("alpha"), A_DEFFLOAT,0); + class_addmethod (mtx_decay_class, (t_method) mTXSetDecayDimension, gensym("dimension"), A_DEFFLOAT,0); + class_addmethod (mtx_decay_class, (t_method) mTXSetDecayDirection, gensym("direction"), A_DEFFLOAT,0); + class_sethelpsymbol (mtx_decay_class, gensym("iemmatrix/mtx_decay")); +} + +void iemtx_decay_setup(void){ + mtx_decay_setup(); +} diff --git a/src/mtx_rowrfft.c b/src/mtx_rowrfft.c new file mode 100644 index 0000000..e7f0551 --- /dev/null +++ b/src/mtx_rowrfft.c @@ -0,0 +1,205 @@ +/* + * 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_rowrfft_class; + +typedef struct _MTXRowrfft_ MTXRowrfft; +struct _MTXRowrfft_ +{ + t_object x_obj; + int rows; + int columns; + int columns_re; + int size; + int size2; + t_float renorm_fac; + + t_float *f_re; + t_float *f_im; + + t_outlet *list_re_out; + t_outlet *list_im_out; + + t_atom *list_re; + t_atom *list_im; +}; + +static void deleteMTXRowrfft (MTXRowrfft *mtx_rowrfft_obj) +{ + if (mtx_rowrfft_obj->f_re) + freebytes (mtx_rowrfft_obj->f_re, sizeof(t_float)*mtx_rowrfft_obj->size); + if (mtx_rowrfft_obj->f_im) + freebytes (mtx_rowrfft_obj->f_im, sizeof(t_float)*mtx_rowrfft_obj->size); + if (mtx_rowrfft_obj->list_re) + freebytes (mtx_rowrfft_obj->list_re, sizeof(t_atom)*(mtx_rowrfft_obj->size2+2)); + if (mtx_rowrfft_obj->list_im) + freebytes (mtx_rowrfft_obj->list_im, sizeof(t_atom)*(mtx_rowrfft_obj->size2+2)); +} + +static void *newMTXRowrfft (t_symbol *s, int argc, t_atom *argv) +{ + MTXRowrfft *mtx_rowrfft_obj = (MTXRowrfft *) pd_new (mtx_rowrfft_class); + mtx_rowrfft_obj->list_re_out = outlet_new (&mtx_rowrfft_obj->x_obj, gensym("matrix")); + mtx_rowrfft_obj->list_im_out = outlet_new (&mtx_rowrfft_obj->x_obj, gensym("matrix")); + return ((void *) mtx_rowrfft_obj); +} + +static void mTXrowrfftBang (MTXRowrfft *mtx_rowrfft_obj) +{ + if (mtx_rowrfft_obj->list_im) { + outlet_anything(mtx_rowrfft_obj->list_im_out, gensym("matrix"), mtx_rowrfft_obj->size2+2, mtx_rowrfft_obj->list_im); + outlet_anything(mtx_rowrfft_obj->list_re_out, gensym("matrix"), mtx_rowrfft_obj->size2+2, mtx_rowrfft_obj->list_re); + } +} + +static void fftRestoreImag (int n, t_float *re, t_float *im) +{ + t_float *im2; + n >>= 1; + *im=0; + re += n; + im += n; + im2 = im; + *im=0; + while (--n) { + *--im = -*++re; + *++im2 = 0; + *re = 0; + } +} + +static void zeroFloatArray (int n, t_float *f) +{ + while (n--) + *f++ = 0.0f; +} + +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 mTXrowrfftMatrix (MTXRowrfft *mtx_rowrfft_obj, t_symbol *s, + int argc, t_atom *argv) +{ + //mTXrowrfftList (mtx_rowrfft_obj, s, argc-2, argv+2); + int rows = atom_getint (argv++); + int columns = atom_getint (argv++); + int columns_re = (columns>>1)+1; + int size = rows * columns; + int in_size = argc-2; + int size2 = columns_re * rows; + int fft_count; + t_atom *ptr_re = mtx_rowrfft_obj->list_re; + t_atom *ptr_im = mtx_rowrfft_obj->list_im; + t_float *f_re = mtx_rowrfft_obj->f_re; + t_float *f_im = mtx_rowrfft_obj->f_im; + + // fftsize check + if (!size) + post("mtx_rowrfft: invalid dimensions"); + else if (in_size<size) + post("mtx_rowrfft: sparse matrix not yet supported: use \"mtx_check\""); + else if (columns == (1 << ilog2(columns))) { + // memory things + if (f_re) { + if (size != mtx_rowrfft_obj->size) { + f_re = (t_float *) resizebytes (f_re, + sizeof (t_float) * mtx_rowrfft_obj->size, + sizeof (t_float) * size); + f_im = (t_float *) resizebytes (f_im, + sizeof (t_float) * mtx_rowrfft_obj->size, + sizeof (t_float) * size); + ptr_re = (t_atom *) resizebytes (ptr_re, + sizeof (t_atom) * (mtx_rowrfft_obj->size2+2), + sizeof (t_atom) * (size2 + 2)); + ptr_im = (t_atom *) resizebytes (ptr_im, + sizeof (t_atom) * (mtx_rowrfft_obj->size2+2), + sizeof (t_atom) * (size2 + 2)); + } + } + else { + f_re = (t_float *) getbytes (sizeof (t_float) * size); + f_im = (t_float *) getbytes (sizeof (t_float) * size); + ptr_re = (t_atom *) getbytes (sizeof (t_atom) * (size2+2)); + ptr_im = (t_atom *) getbytes (sizeof (t_atom) * (size2+2)); + } + mtx_rowrfft_obj->size = size; + mtx_rowrfft_obj->size2 = size2; + mtx_rowrfft_obj->rows = rows; + mtx_rowrfft_obj->columns = columns; + mtx_rowrfft_obj->columns_re = columns_re; + mtx_rowrfft_obj->list_im = ptr_im; + mtx_rowrfft_obj->list_re = ptr_re; + mtx_rowrfft_obj->f_re = f_re; + mtx_rowrfft_obj->f_im = f_im; + + // main part + readFloatFromList (size, argv, f_re); + + fft_count = rows; + ptr_re += 2; + ptr_im += 2; + while (fft_count--){ + mayer_realfft (columns, f_re); + fftRestoreImag (columns, f_re, f_im); + writeFloatIntoList (columns_re, ptr_re, f_re); + writeFloatIntoList (columns_re, ptr_im, f_im); + f_im += columns; + f_re += columns; + ptr_re += columns_re; + ptr_im += columns_re; + } + ptr_re = mtx_rowrfft_obj->list_re; + ptr_im = mtx_rowrfft_obj->list_im; + + SETSYMBOL(ptr_re, gensym("matrix")); + SETSYMBOL(ptr_im, gensym("matrix")); + SETFLOAT(ptr_re, rows); + SETFLOAT(ptr_im, rows); + SETFLOAT(&ptr_re[1], columns_re); + SETFLOAT(&ptr_im[1], columns_re); + outlet_anything(mtx_rowrfft_obj->list_im_out, gensym("matrix"), + mtx_rowrfft_obj->size2+2, ptr_im); + outlet_anything(mtx_rowrfft_obj->list_re_out, gensym("matrix"), + mtx_rowrfft_obj->size2+2, ptr_re); + } + else + post("mtx_rowfft: rowvector size no power of 2!"); +} + +void mtx_rowrfft_setup (void) +{ + mtx_rowrfft_class = class_new + (gensym("mtx_rowrfft"), + (t_newmethod) newMTXRowrfft, + (t_method) deleteMTXRowrfft, + sizeof (MTXRowrfft), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (mtx_rowrfft_class, (t_method) mTXrowrfftBang); + class_addmethod (mtx_rowrfft_class, (t_method) mTXrowrfftMatrix, gensym("matrix"), A_GIMME,0); + class_sethelpsymbol (mtx_rowrfft_class, gensym("iemmatrix/mtx_rowrfft")); +} + +void iemtx_rowrfft_setup(void){ + mtx_rowrfft_setup(); +} diff --git a/src/mtx_rowrifft.c b/src/mtx_rowrifft.c new file mode 100644 index 0000000..9eaba9c --- /dev/null +++ b/src/mtx_rowrifft.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_rowrifft_class; + +typedef struct _MTXRowrifft_ +{ + t_object x_obj; + int rows; + int columns; + int columns_re; + int size; + int size2; + t_float renorm_fac; + + t_float *f_re; + t_float *f_im; + + t_outlet *list_re_out; + t_outlet *list_im_out; + + t_atom *list_re; + t_atom *list_im; +} MTXRowrifft; + + +// helper functions: these should really go into a separate file! + + +static void zeroFloatArray (int n, t_float *f) +{ + while (n--) + *f++ = 0.0f; +} + +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++); +} + +//--------------inverse real fft + +static void multiplyVector (int n, t_float *f, t_float fac) +{ + while (n--) + *f++ *= fac; +} + + +static void ifftPrepareReal (int n, t_float *re, t_float *im) +{ + n >>= 1; + re += n; + im += n; + + while (--n) + *++re = -*--im; +} + + +static void *newMTXRowrifft (t_symbol *s, int argc, t_atom *argv) +{ + MTXRowrifft *mtx_rowrifft_obj = (MTXRowrifft *) pd_new (mtx_rowrifft_class); + inlet_new(&mtx_rowrifft_obj->x_obj, &mtx_rowrifft_obj->x_obj.ob_pd, gensym("matrix"),gensym("")); + mtx_rowrifft_obj->list_re_out = outlet_new (&mtx_rowrifft_obj->x_obj, gensym("matrix")); + return ((void *) mtx_rowrifft_obj); +} + + +static void mTXrowrifftMatrixCold (MTXRowrifft *mtx_rowrifft_obj, t_symbol *s, + int argc, t_atom *argv) +{ + //mTXrowrifftList (mtx_rowrifft_obj, s, argc-2, argv+2); + int rows = atom_getint (argv++); + int columns_re = atom_getint (argv++); + int in_size = argc-2; + int columns = (columns_re-1)<<1; + int size2 = columns_re * rows; + int size = rows * columns; + int ifft_count; + t_atom *ptr_re = mtx_rowrifft_obj->list_re; + t_float *f_re = mtx_rowrifft_obj->f_re; + t_float *f_im = mtx_rowrifft_obj->f_im; + + // ifftsize check + if (!size) + post("mtx_rowrifft: invalid dimensions"); + else if (in_size < size2) + post("mtx_rowrifft: sparse matrix not yet supported: use \"mtx_check\""); + else if (columns == (1 << ilog2(columns))) { + // memory things + if (f_re) { + if (size != mtx_rowrifft_obj->size) { + f_re = (t_float *) resizebytes (f_re, + sizeof (t_float) * mtx_rowrifft_obj->size, + sizeof (t_float) * size); + f_im = (t_float *) resizebytes (f_im, + sizeof (t_float) * mtx_rowrifft_obj->size, + sizeof (t_float) * size); + ptr_re = (t_atom *) resizebytes (ptr_re, + sizeof (t_atom) * (mtx_rowrifft_obj->size + 2), + sizeof (t_atom) * (size + 2)); + } + } + else { + f_re = (t_float *) getbytes (sizeof (t_float) * size); + f_im = (t_float *) getbytes (sizeof (t_float) * size); + ptr_re = (t_atom *) getbytes (sizeof (t_atom) * (size + 2)); + } + mtx_rowrifft_obj->size = size; + mtx_rowrifft_obj->size2 = size2; + mtx_rowrifft_obj->rows = rows; + mtx_rowrifft_obj->columns = columns; + mtx_rowrifft_obj->columns_re = columns_re; + mtx_rowrifft_obj->list_re = ptr_re; + mtx_rowrifft_obj->f_re = f_re; + mtx_rowrifft_obj->f_im = f_im; + + // main part: reading imaginary part + ifft_count = rows; + mtx_rowrifft_obj->renorm_fac = 1.0f / columns; + while (ifft_count--) { + readFloatFromList (columns_re, argv, f_im); + argv += columns_re; + f_im += columns; + } + // do nothing else! + } + else + post("mtx_rowrifft: rowvector size no power of 2!"); +} + +static void mTXrowrifftMatrixHot (MTXRowrifft *mtx_rowrifft_obj, t_symbol *s, + int argc, t_atom *argv) +{ + //mTXrowrifftList (mtx_rowrifft_obj, s, argc-2, argv+2); + int rows = atom_getint (argv++); + int columns_re = atom_getint (argv++); + int columns = mtx_rowrifft_obj->columns; + int size = mtx_rowrifft_obj->size; + int in_size = argc-2; + int size2 = mtx_rowrifft_obj->size2; + int ifft_count; + t_atom *ptr_re = mtx_rowrifft_obj->list_re; + t_float *f_re = mtx_rowrifft_obj->f_re; + t_float *f_im = mtx_rowrifft_obj->f_im; + t_float renorm_fac; + + // ifftsize check + if ((rows != mtx_rowrifft_obj->rows) || + (columns_re != mtx_rowrifft_obj->columns_re)) + post("mtx_rowrifft: matrix dimensions do not match"); + else if (in_size<size2) + post("mtx_rowrifft: sparse matrix not yet supported: use \"mtx_check\""); + else if (!mtx_rowrifft_obj->size2) + post("mtx_rowrifft: invalid right side matrix"); + else { // main part + ifft_count = rows; + ptr_re += 2; + renorm_fac = mtx_rowrifft_obj->renorm_fac; + while (ifft_count--){ + readFloatFromList (columns_re, argv, f_re); + ifftPrepareReal (columns, f_re, f_im); + mayer_realifft (columns, f_re); + multiplyVector (columns, f_re, renorm_fac); + f_im += columns; + f_re += columns; + ptr_re += columns; + argv += columns_re; + } + ptr_re = mtx_rowrifft_obj->list_re; + f_re = mtx_rowrifft_obj->f_re; + size2 = mtx_rowrifft_obj->size2; + + SETSYMBOL(ptr_re, gensym("matrix")); + SETFLOAT(ptr_re, rows); + SETFLOAT(&ptr_re[1], mtx_rowrifft_obj->columns); + writeFloatIntoList (size, ptr_re+2, f_re); + outlet_anything(mtx_rowrifft_obj->list_re_out, gensym("matrix"), size+2, ptr_re); + } +} + +static void mTXrowrifftBang (MTXRowrifft *mtx_rowrifft_obj) +{ + if (mtx_rowrifft_obj->list_re) + outlet_anything(mtx_rowrifft_obj->list_re_out, gensym("matrix"), + mtx_rowrifft_obj->size+2, mtx_rowrifft_obj->list_re); +} + + +static void deleteMTXRowrifft (MTXRowrifft *mtx_rowrfft_obj) +{ + if (mtx_rowrfft_obj->f_re) + freebytes (mtx_rowrfft_obj->f_re, sizeof(t_float)*mtx_rowrfft_obj->size); + if (mtx_rowrfft_obj->f_im) + freebytes (mtx_rowrfft_obj->f_im, sizeof(t_float)*mtx_rowrfft_obj->size); + if (mtx_rowrfft_obj->list_re) + freebytes (mtx_rowrfft_obj->list_re, sizeof(t_atom)*(mtx_rowrfft_obj->size2+2)); + if (mtx_rowrfft_obj->list_im) + freebytes (mtx_rowrfft_obj->list_im, sizeof(t_atom)*(mtx_rowrfft_obj->size2+2)); +} + +static void mtx_rowrifft_setup (void) +{ + mtx_rowrifft_class = class_new + (gensym("mtx_rowrifft"), + (t_newmethod) newMTXRowrifft, + (t_method) deleteMTXRowrifft, + sizeof (MTXRowrifft), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (mtx_rowrifft_class, (t_method) mTXrowrifftBang); + class_addmethod (mtx_rowrifft_class, (t_method) mTXrowrifftMatrixHot, gensym("matrix"), A_GIMME,0); + class_addmethod (mtx_rowrifft_class, (t_method) mTXrowrifftMatrixCold, gensym(""), A_GIMME,0); + class_sethelpsymbol (mtx_rowrifft_class, gensym("iemmatrix/mtx_rowrfft")); +} + +void iemtx_rowrifft_setup(void){ + mtx_rowrifft_setup(); +} diff --git a/src/mtx_slice.c b/src/mtx_slice.c new file mode 100644 index 0000000..7dc1042 --- /dev/null +++ b/src/mtx_slice.c @@ -0,0 +1,215 @@ +/* + * 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_slice_class; + +typedef struct _MTXslice_ MTXslice; +struct _MTXslice_ +{ + t_object x_obj; + int slice_size; + int slice_startcol; + int slice_startrow; + int slice_stopcol; + int slice_stoprow; + + t_outlet *list_outlet; + + t_atom *list_out; +}; + +static void deleteMTXSlice (MTXslice *mtx_slice_obj) +{ + if (mtx_slice_obj->list_out) + freebytes (mtx_slice_obj->list_out, sizeof(t_atom)*(mtx_slice_obj->slice_size+2)); +} + +static void mTXSliceIndexList (MTXslice *mtx_slice_obj, t_symbol *s, + int argc, t_atom *argv) +{ + int startcol; + int startrow; + int stopcol; + int stoprow; + t_symbol *endsym = gensym("end"); + t_atom *list_out = mtx_slice_obj->list_out; + + if (argc<4) { + post("mtx_slice: invalid index vector: <startrow><startcol><stoprow><stopcol>"); + return; + } + startrow = atom_getint(&argv[0]); + startcol = atom_getint(&argv[1]); + stoprow = atom_getint(&argv[2]); + stopcol = atom_getint(&argv[3]); + if (atom_getsymbol(&argv[0])==endsym) { + startrow = -1; + } + if (atom_getsymbol(&argv[1])==endsym) { + startcol = -1; + } + if (atom_getsymbol(&argv[2])==endsym) { + stoprow = -1; + } + if (atom_getsymbol(&argv[3])==endsym) { + stopcol = -1; + } + + if (((startrow<1) && (atom_getsymbol(&argv[0])!=endsym)) || + ((startcol<1) && (atom_getsymbol(&argv[1])!=endsym))) { + post("mtx_slice: row and column indices must be >0, or misused \"end\" keyword"); + return; + } + + if (((startrow>stoprow) && (atom_getsymbol(&argv[2])!=endsym)) || + ((startcol>stopcol) && (atom_getsymbol (&argv[3])!=endsym))) { + post("mtx_slice: start_index<stop_index for rows and columns, or misused \"end\" keyword"); + return; + } + + mtx_slice_obj->slice_startrow = startrow; + mtx_slice_obj->slice_startcol = startcol; + mtx_slice_obj->slice_stoprow = stoprow; + mtx_slice_obj->slice_stopcol = stopcol; +} + +static void *newMTXSlice (t_symbol *s, int argc, t_atom *argv) +{ + MTXslice *mtx_slice_obj = (MTXslice *) pd_new (mtx_slice_class); + if (argc==4) + mTXSliceIndexList (mtx_slice_obj, gensym("list"),argc,argv); + else { + mtx_slice_obj->slice_startrow = 1; + mtx_slice_obj->slice_startcol = 1; + mtx_slice_obj->slice_stopcol = -1; + mtx_slice_obj->slice_stoprow = -1; + } + mtx_slice_obj->list_outlet = outlet_new (&mtx_slice_obj->x_obj, gensym("matrix")); + inlet_new(&mtx_slice_obj->x_obj, &mtx_slice_obj->x_obj.ob_pd, gensym("list"),gensym("")); + return ((void *) mtx_slice_obj); +} + +static void mTXSliceBang (MTXslice *mtx_slice_obj) +{ + if (mtx_slice_obj->list_out) + outlet_anything(mtx_slice_obj->list_outlet, gensym("matrix"), + mtx_slice_obj->slice_size+2, mtx_slice_obj->list_out); +} +/* + static void copyList (int size, t_atom *x, t_atom *y) + { + while(size--) + *y++=*x++; + } +*/ + +static void writeVectorIntoList (int n, t_atom *x, t_atom *y) +{ + for (;n--;x++,y++) + *y = *x; +} + +static void writeSliceIntoList (int slicerows, const int slicecols, int columns, t_atom *x, t_atom *y) +{ + for (;slicerows--;x+=columns,y+=slicecols) + writeVectorIntoList(slicecols, x, y); +} + +static void mTXSliceMatrix (MTXslice *mtx_slice_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_slice_obj->list_out; + int stopcol = mtx_slice_obj->slice_stopcol; + int stoprow = mtx_slice_obj->slice_stoprow; + int startrow = mtx_slice_obj->slice_startrow; + int startcol = mtx_slice_obj->slice_startcol; + int slicecols, slicerows, slicesize; + + // size check + if (!size) { + post("mtx_slice: invalid dimensions"); + return; + } + else if (list_size<size) { + post("mtx_slice: sparse matrix not yet supported: use \"mtx_check\""); + return; + } + startrow = (startrow==-1)?rows:startrow; + startcol = (startcol==-1)?columns:startcol; + stoprow = (stoprow==-1)?rows:stoprow; + stopcol = (stopcol==-1)?columns:stopcol; + if ((!startrow)||(!startcol)) { + post("mtx_slice: indices must be >0"); + return; + } + if ((stopcol > columns) || + (stoprow > rows)) { + post("mtx_slice: slice index exceeds matrix dimensions"); + return; + } + if ((stoprow<startrow) || (stopcol<startcol)) { + post("mtx_slice: start_index<stop_index for rows and columns, or misused \"end\" keyword"); + return; + } + slicerows = stoprow-startrow+1; + slicecols = stopcol-startcol+1; + slicesize = slicerows*slicecols; + + // main part + if (slicesize != mtx_slice_obj->slice_size) { + if (!list_out) + list_out = (t_atom *) getbytes (sizeof (t_atom) * (slicesize + 2)); + else + list_out = (t_atom *) resizebytes (list_out, + sizeof (t_atom) * (mtx_slice_obj->slice_size+2), + sizeof (t_atom) * (slicesize + 2)); + mtx_slice_obj->slice_size = slicesize; + mtx_slice_obj->list_out = list_out; + } + list_out += 2; + list_in += columns * (startrow-1) + startcol-1; + writeSliceIntoList (slicerows, slicecols, + columns, list_in,list_out); + list_out = mtx_slice_obj->list_out; + SETSYMBOL(list_out, gensym("matrix")); + SETFLOAT(list_out, slicerows); + SETFLOAT(&list_out[1], slicecols); + outlet_anything(mtx_slice_obj->list_outlet, gensym("matrix"), + slicesize+2, list_out); +} + +void mtx_slice_setup (void) +{ + mtx_slice_class = class_new + (gensym("mtx_slice"), + (t_newmethod) newMTXSlice, + (t_method) deleteMTXSlice, + sizeof (MTXslice), + CLASS_DEFAULT, A_GIMME, 0); + class_addbang (mtx_slice_class, (t_method) mTXSliceBang); + class_addmethod (mtx_slice_class, (t_method) mTXSliceMatrix, gensym("matrix"), A_GIMME,0); + class_addmethod (mtx_slice_class, (t_method) mTXSliceIndexList, gensym(""), A_GIMME,0); + class_sethelpsymbol (mtx_slice_class, gensym("iemmatrix/mtx_slice")); +} + +void iemtx_slice_setup(void){ + mtx_slice_setup(); +} |