[PD-cvs] externals/iem/iemmatrix/src mtx_colon.c, NONE, 1.1 mtx_conv.c, NONE, 1.1 mtx_cumsum.c, NONE, 1.1 mtx_diff.c, NONE, 1.1 mtx_fill.c, NONE, 1.1 mtx_find.c, NONE, 1.1 mtx_index.c, NONE, 1.1 mtx_minmax.c, NONE, 1.1 mtx_not.c, NONE, 1.1 mtx_repmat.c, NONE, 1.1 mtx_reverse.c, NONE, 1.1 mtx_sort.c, NONE, 1.1 iemmatrix_sources.c, 1.2, 1.3 iemmatrix_sources.h, 1.2, 1.3

IOhannes m zmölnig zmoelnig at users.sourceforge.net
Mon Sep 19 16:47:52 CEST 2005


Update of /cvsroot/pure-data/externals/iem/iemmatrix/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5954

Modified Files:
	iemmatrix_sources.c iemmatrix_sources.h 
Added Files:
	mtx_colon.c mtx_conv.c mtx_cumsum.c mtx_diff.c mtx_fill.c 
	mtx_find.c mtx_index.c mtx_minmax.c mtx_not.c mtx_repmat.c 
	mtx_reverse.c mtx_sort.c 
Log Message:
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)


Index: iemmatrix_sources.c
===================================================================
RCS file: /cvsroot/pure-data/externals/iem/iemmatrix/src/iemmatrix_sources.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** iemmatrix_sources.c	19 Sep 2005 13:28:51 -0000	1.2
--- iemmatrix_sources.c	19 Sep 2005 14:47:48 -0000	1.3
***************
*** 19,26 ****
--- 19,30 ----
  	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 */
***************
*** 29,35 ****
--- 33,42 ----
  	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 */
***************
*** 41,47 ****
--- 48,56 ----
  	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 */
***************
*** 51,55 ****
--- 60,66 ----
  	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 */
***************
*** 58,61 ****
--- 69,73 ----
  	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 */

--- NEW FILE: mtx_index.c ---
/*
 *  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();
}

--- NEW FILE: mtx_sort.c ---
/*
 *  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();
}

--- NEW FILE: mtx_colon.c ---
/*
 *  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();
}

Index: iemmatrix_sources.h
===================================================================
RCS file: /cvsroot/pure-data/externals/iem/iemmatrix/src/iemmatrix_sources.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** iemmatrix_sources.h	19 Sep 2005 13:28:51 -0000	1.2
--- iemmatrix_sources.h	19 Sep 2005 14:47:49 -0000	1.3
***************
*** 17,24 ****
--- 17,28 ----
  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 */
***************
*** 27,33 ****
--- 31,40 ----
  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 */
***************
*** 39,45 ****
--- 46,54 ----
  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 */
***************
*** 49,53 ****
--- 58,64 ----
  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 */
***************
*** 56,59 ****
--- 67,71 ----
  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 */

--- NEW FILE: mtx_not.c ---
/*
 *  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();
}

--- NEW FILE: mtx_find.c ---
/*
 *  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();
}

--- NEW FILE: mtx_diff.c ---
/*
 *  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();
}

--- NEW FILE: mtx_fill.c ---
/*
 *  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();
}

--- NEW FILE: mtx_minmax.c ---
/*
 *  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();
}

--- NEW FILE: mtx_repmat.c ---
/*
 *  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();
}

--- NEW FILE: mtx_reverse.c ---
/*
 *  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();
}

--- NEW FILE: mtx_cumsum.c ---
/*
 *  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();
}

--- NEW FILE: mtx_conv.c ---
/*
 *  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();
}





More information about the Pd-cvs mailing list