diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-03-21 14:33:31 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-03-21 14:33:31 +0000 |
commit | 10b474fba485e9a93157c7fa534bb66e7bcc6fde (patch) | |
tree | 73e9e02738ea62179a1722b37ef49a9e91cfcbad /src |
This commit was generated by cvs2svn to compensate for changes in r2637,svn2git-root
which included commits to RCS files with non-trunk default branches.
svn path=/trunk/externals/iem/iemmatrix/; revision=2638
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 80 | ||||
-rw-r--r-- | src/configure.in | 193 | ||||
-rw-r--r-- | src/iemmatrix.c | 77 | ||||
-rw-r--r-- | src/iemmatrix.h | 95 | ||||
-rw-r--r-- | src/make.source | 1 | ||||
-rw-r--r-- | src/mtx_binops.c | 680 | ||||
-rw-r--r-- | src/mtx_check.c | 76 | ||||
-rw-r--r-- | src/mtx_col.c | 129 | ||||
-rw-r--r-- | src/mtx_diag.c | 59 | ||||
-rw-r--r-- | src/mtx_diegg.c | 56 | ||||
-rw-r--r-- | src/mtx_egg.c | 58 | ||||
-rw-r--r-- | src/mtx_element.c | 118 | ||||
-rw-r--r-- | src/mtx_eye.c | 60 | ||||
-rw-r--r-- | src/mtx_inverse.c | 118 | ||||
-rw-r--r-- | src/mtx_matrix.c | 606 | ||||
-rw-r--r-- | src/mtx_mean.c | 61 | ||||
-rw-r--r-- | src/mtx_ones.c | 56 | ||||
-rw-r--r-- | src/mtx_pivot.c | 171 | ||||
-rw-r--r-- | src/mtx_print.c | 60 | ||||
-rw-r--r-- | src/mtx_rand.c | 93 | ||||
-rw-r--r-- | src/mtx_resize.c | 103 | ||||
-rw-r--r-- | src/mtx_roll.c | 73 | ||||
-rw-r--r-- | src/mtx_row.c | 120 | ||||
-rw-r--r-- | src/mtx_scroll.c | 59 | ||||
-rw-r--r-- | src/mtx_size.c | 54 | ||||
-rw-r--r-- | src/mtx_tilde.c | 413 | ||||
-rw-r--r-- | src/mtx_trace.c | 57 | ||||
-rw-r--r-- | src/mtx_transpose.c | 67 | ||||
-rw-r--r-- | src/mtx_zeros.c | 56 |
29 files changed, 3849 insertions, 0 deletions
diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..bbb76c5 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,80 @@ +LIBNAME =iemmatrix + +PREFIX =@prefix@@PDLIBDIR@ + +INSTALL_BIN=$(PREFIX)/extra +INSTALL_DOC=$(PREFIX)/@REFERENCEPATH@$(LIBNAME) + +EXT = @EXT@ +DEFS = @DFLAGS@ +IFLAGS = -I. @INCLUDES@ + +CC = @CC@ +LD = @LD@ +AFLAGS = +LFLAGS = @LFLAGS@ +WFLAGS = + +TARNAME = $(LIBNAME)-@IEMMATRIX_VERSION@.tgz + +.SUFFIXES: .$(EXT) + +PDCFLAGS = -g -O2 $(DEFS) $(IFLAGS) $(WFLAGS) $(LFLAGS) $(AFLAGS) +CFLAGS = -g -O2 $(DEFS) $(IFLAGS) $(WFLAGS) + +LIBS = @LIBS@ +#LIBS = -lpthread -lm -lc +include Make.source +TARGETS = $(SOURCES:.c=.o) + + +all: $(LIBNAME) + cp $(LIBNAME).$(EXT) .. + +$(LIBNAME): $(TARGETS) + $(LD) $(LFLAGS) -o $(LIBNAME).$(EXT) *.o $(LIBS) + strip @STRIPFLAGS@ $(LIBNAME).$(EXT) + +.c.o: + $(CC) -c -o $@ $(CFLAGS) -DPD $*.c + +# cp $@ $*_stat.o + +.o.$(EXT): + $(CC) -o $@ $(PDCFLAGS) -DPD $*.o + + +clean: + -rm -f *.$(EXT) *.o + +cleaner: clean + -rm -f *~ _* config.* + +cleanest: cleaner + -rm -f Makefile ../*.$(EXT) Make.source + +distclean: cleanest newmakefile + +install: install-bin install-doc + +install-bin: + -install -d $(INSTALL_BIN) + -install -m 644 $(LIBNAME).$(EXT) $(INSTALL_BIN) + +install-doc: + -install -d $(INSTALL_DOC) + -install -m 644 ../doc/*.pd $(INSTALL_DOC) + +dist: all cleaner + (cd ../..;tar czvf $(TARNAME) $(LIBNAME)) + +everything: clean all install distclean + +newmakefile: + echo "current:">Makefile + echo " ./configure && make">>Makefile + +source: + echo "SOURCES = \\"> Make.source + echo `ls mtx_*.c $(LIBNAME).c` >> Make.source + echo >> Make.source diff --git a/src/configure.in b/src/configure.in new file mode 100644 index 0000000..9afbf9e --- /dev/null +++ b/src/configure.in @@ -0,0 +1,193 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(iemmatrix.c) + +dnl Checks for programs. +AC_PROG_CC + +AC_SUBST(STK) +AC_SUBST(DFLAGS) +AC_SUBST(LFLAGS) +AC_SUBST(EXT) +AC_SUBST(LD) +AC_SUBST(STRIPFLAGS) +AC_SUBST(IEMMATRIX_VERSION) +AC_SUBST(REFERENCEPATH) +AC_SUBST(PDLIBDIR) +AC_SUBST(INCLUDES) +AC_SUBST(SOURCES) + + +AC_ARG_WITH(pdversion, [ --with-pdversion=<ver> enforce a certain pd-version (e.g. 0.37)]) + +if test $includedir +then + for id in $includedir + do + if test -d $id + then + INCLUDES="-I$id $INCLUDES" + fi + done +fi + +dnl Checks for libraries. +dnl Replace `main' with a function in -lc: +AC_CHECK_LIB(c, main) +dnl Replace `main' with a function in -lm: +AC_CHECK_LIB(m, main) +dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl Replace `main' with a function in -lstk: +dnl AC_CHECK_LIB(stk, main, STK=yes) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_TIME + +dnl Checks for library functions. +AC_FUNC_MMAP +AC_CHECK_FUNCS(select socket strerror) + + +LD=ld +DFLAGS="" + +dnl +dnl OK, checks for machines are here now +dnl +if test `uname -s` = Linux; +then + LFLAGS="-export_dynamic -shared" + EXT=pd_linux + STRIPFLAGS="--strip-unneeded" +fi + +dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress' +dnl then strip might do something +if test `uname -s` = Darwin; +then + LD=cc + LFLAGS="-bundle -undefined suppress -flat_namespace" + EXT=pd_darwin + STRIPFLAGS= + if test "$enable_lpt" = "yes"; then + AC_MSG_ERROR("lpt not supported on this platform"); + fi + if test "$enable_lpt" = ""; then + AC_MSG_WARN("lpt not supported on this platform - disabling"); + enable_lpt="no"; + fi +fi +if test `uname | sed -e 's/^MINGW.*/NT/'` = NT; +then + LD=gcc + INCLUDES="-I@prefix@/src" + DFLAGS="-DMSW -DNT" + LFLAGS="-shared @prefix@/bin/pd.dll" + EXT=dll +else + PDLIBDIR="/lib/pd" + LIBS="-lc -lm" +fi +if test `uname -s` = IRIX64; +then + LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -shared -rdata_shared" + EXT=pd_irix6 + dnl DFLAGS="-DUNIX -DIRIX6" + STRIPFLAGS="--strip-unneeded" + if test "$enable_lpt" = "yes"; then + AC_MSG_ERROR("lpt not supported on this platform"); + fi + if test "$enable_lpt" = ""; then + AC_MSG_WARN("lpt not supported on this platform - disabling"); + enable_lpt="no"; + fi +fi + +if test `uname -s` = IRIX32; +then + LFLAGS="-o32 -DUNIX -DIRIX -O2 + -shared -rdata_shared" + EXT=pd_irix5 + dnl DFLAGS="-DUNIX -DIRIX5" + STRIPFLAGS="--strip-unneeded" + if test "$enable_lpt" = "yes"; then + AC_MSG_ERROR("lpt not supported on this platform"); + fi + if test "$enable_lpt" = ""; then + AC_MSG_WARN("lpt not supported on this platform - disabling"); + enable_lpt="no"; + fi +fi + +dnl Checks for pd-version, to set the correct help-path +AC_MSG_CHECKING("pd\>=0.37") + +if test "$with_pdversion" != "" +then +echo -n "($with_pdversion)... " + PD_VERSION="$with_pdversion" +else +cat > conftest.c << EOF +#include <stdio.h> +#include "m_pd.h" +int main(){ + printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION); + return 0; +} +EOF + if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1 + then + PD_VERSION=`./conftest.o` + else + PD_VERSION="" + fi +fi + +let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0 +let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0 + +if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37 +then + REFERENCEPATH=extra/help- + echo "yes" +else + REFERENCEPATH=doc/5.reference/ + echo "no" +fi + +dnl check for iemmatrix-version (but why...) +AC_MSG_CHECKING("iemmatrix-version") +cat > conftest.c << EOF +#include <stdio.h> +#include "iemmatrix.h" +int main(){ + printf("%s\n", VERSION); + return 0; +} +EOF + +if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1 +then + IEMMATRIX_VERSION=`./conftest.o` + echo "$IEMMATRIX_VERSION" +else + IEMMATRIX_VERSION="" + echo "(unknown)" +fi + +echo "SOURCES = \\"> Make.source +for i in `ls mtx_*.c iemmatrix.c` +do + echo " $i\\">> Make.source +done +echo >> Make.source + +AC_OUTPUT(Makefile) + +rm -f conftest.* diff --git a/src/iemmatrix.c b/src/iemmatrix.c new file mode 100644 index 0000000..384f54a --- /dev/null +++ b/src/iemmatrix.c @@ -0,0 +1,77 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +void mtx_binops_setup(); +void mtx_col_setup(); +void mtx_diag_setup(); +void mtx_diegg_setup(); +void mtx_egg_setup(); +void mtx_element_setup(); +void mtx_eye_setup(); +void mtx_inverse_setup(); +void mtx_matrix_setup(); +void mtx_mean_setup(); +void mtx_check_setup(); +void mtx_print_setup(); +void mtx_ones_setup(); +void mtx_pivot_setup(); +void mtx_rand_setup(); +void mtx_resize_setup(); +void mtx_roll_setup(); +void mtx_row_setup(); +void mtx_scroll_setup(); +void mtx_size_setup(); +void mtx_trace_setup(); +void mtx_transpose_setup(); +void mtx_zeros_setup(); +void mtx_tilde_setup(); + +void iemtx_setup(){ + mtx_binops_setup(); + mtx_col_setup(); + mtx_diag_setup(); + mtx_diegg_setup(); + mtx_egg_setup(); + mtx_element_setup(); + mtx_eye_setup(); + mtx_inverse_setup(); + mtx_matrix_setup(); + mtx_mean_setup(); + mtx_check_setup(); + mtx_print_setup(); + mtx_ones_setup(); + mtx_pivot_setup(); + mtx_rand_setup(); + mtx_resize_setup(); + mtx_roll_setup(); + mtx_row_setup(); + mtx_scroll_setup(); + mtx_size_setup(); + mtx_trace_setup(); + mtx_transpose_setup(); + mtx_zeros_setup(); + mtx_tilde_setup(); +} + +void iemmatrix_setup(){ + post(""); + post("iemmatrix "VERSION); + post("\tobjects for manipulating 2d-matrices"); + post("\t(c) IOhannes m zmölnig, Thomas Musil :: iem, 2001-2005"); + post("\tcompiled "__DATE__" : "__TIME__); + post(""); + + iemtx_setup(); +} diff --git a/src/iemmatrix.h b/src/iemmatrix.h new file mode 100644 index 0000000..aeaec85 --- /dev/null +++ b/src/iemmatrix.h @@ -0,0 +1,95 @@ +/* ************************************* */ +/* iemmatrix */ +/* ************************************* */ +/* objects for simple matrix operations */ +/* ************************************* */ + +/* IEMMATRIX is a runtime-library for miller s. puckette's realtime-computermusic-software "pure data" + * therefore you NEED "pure data" to make any use of the IEMMATRIX external + * (except if you want to use the code for other things) + * download "pure data" at + * + * http://pd.iem.at + * ftp://iem.at/pd + * + * + * IEMMATRIX is published under the Lesser GNU GeneralPublicLicense (LGPL), + * that must be shipped with IEMMATRIX. + * if you are using Debian GNU/linux, + * the lesser GNU-GPL can be found under /usr/share/common-licenses/LGPL + * if you still haven't found a copy of the lesser GNU-GPL, have a look at http://www.gnu.org + * + * "pure data" has it's own license, that comes shipped with "pure data". + * + * there are ABSOLUTELY NO WARRANTIES for anything + */ + +#ifndef INCLUDE_IEMMATRIX_H__ +#define INCLUDE_IEMMATRIX_H__ + +#include "m_pd.h" + +#define VERSION "0.1" + +#ifdef NT +# pragma warning( disable : 4244 ) +# pragma warning( disable : 4305 ) +#endif + +#include <math.h> +#include <stdio.h> + +#include <string.h> +#include <memory.h> + +#ifdef NT +# define fabsf fabs +#endif + +typedef long double t_matrixfloat; + + +/* the main class...*/ +typedef struct _matrix +{ + t_object x_obj; + + int row; + int col; + + t_atom *atombuffer; + + int current_row, current_col; /* this makes things easy for the mtx_row & mtx_col...*/ + t_float f; + + t_canvas *x_canvas; +} t_matrix; + +void matrix_free(t_matrix*x); + +/* utility function */ +void setdimen(t_matrix *x, int row, int col); +void adjustsize(t_matrix *x, int desiredRow, int desiredCol); +void debugmtx(int argc, t_float *buf, int id); +t_matrixfloat *matrix2float(t_atom *ap); +void float2matrix(t_atom *ap, t_matrixfloat *buffer); + +/* basic I/O functions */ +void matrix_bang(t_matrix *x); /* output the matrix stored in atombuffer */ +void matrix_matrix2(t_matrix *x, t_symbol *s, int argc, t_atom *argv); /* store the matrix in atombuffer */ + +/* set data */ +void matrix_set(t_matrix *x, t_float f); /* set the entire matrix to "f" */ +void matrix_zeros(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_ones(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_eye(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_egg(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_diag(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_diegg(t_matrix *x, t_symbol *s, int argc, t_atom *argv); + +/* get/set data */ +void matrix_row(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_col(t_matrix *x, t_symbol *s, int argc, t_atom *argv); +void matrix_element(t_matrix *x, t_symbol *s, int argc, t_atom *argv); + +#endif diff --git a/src/make.source b/src/make.source new file mode 100644 index 0000000..dc22aae --- /dev/null +++ b/src/make.source @@ -0,0 +1 @@ +SOURCES = \ diff --git a/src/mtx_binops.c b/src/mtx_binops.c new file mode 100644 index 0000000..5625667 --- /dev/null +++ b/src/mtx_binops.c @@ -0,0 +1,680 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* + mtx_add + mtx_+ + mtx_mul + mtx_* + mtx_.* + mtx_./ +*/ + +/* -------------------------------------------------------------- */ +/* matrix math */ + +typedef struct _mtx_binscalar +{ + t_object x_obj; + + t_matrix m; // the output matrix + t_float f; // the second input +} t_mtx_binscalar; + +typedef struct _mtx_binmtx +{ + t_object x_obj; + + t_matrix m; // the output matrix + t_matrix m2; // the second input +} t_mtx_binmtx; + +static void mtx_bin_matrix2(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv) +{ + int row = atom_getfloat(argv); + int col = atom_getfloat(argv+1); + if (argc<2){post("mtx_bin2: crippled matrix"); return;} + if ((col<1)||(row<1)) {post("mtx_bin2: invalid dimensions %dx%d", row,col); return;} + if (col*row+2>argc){ post("mtx_bin2: sparse matrix not yet supported : use \"mtx_check\""); return;} + + if (row*col!=x->m2.row*x->m2.col) { + freebytes(x->m2.atombuffer, (x->m2.row*x->m2.col+2)*sizeof(t_atom)); + x->m2.atombuffer=copybytes(argv,(row*col+2)*sizeof(t_atom)); + }else memcpy(x->m2.atombuffer, argv, (row*col+2)*sizeof(t_atom)); + setdimen(&x->m2, row, col); +} + +static void mtx_binmtx_bang(t_mtx_binmtx *x) +{ + if((&x->m)&&(x->m.atombuffer)) + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->m.col*x->m.row+2, x->m.atombuffer); +} + + +static void mtx_binmtx_free(t_mtx_binmtx *x) +{ + matrix_free(&x->m); + matrix_free(&x->m2); +} +static void mtx_binscalar_bang(t_mtx_binscalar *x) +{ + if((&x->m)&&(x->m.atombuffer)) + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->m.col*x->m.row+2, x->m.atombuffer); +} +static void mtx_binscalar_free(t_mtx_binscalar *x) +{ + matrix_free(&x->m); +} + + + +/* mtx_add */ +static t_class *mtx_add_class, *mtx_addscalar_class; + +static void mtx_addscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc-2; + int row=atom_getfloat(argv), col=atom_getfloat(argv+1); + + t_float offset=x->f; + t_atom *buf; + t_atom *ap=argv+2; + + if(argc<2){post("mtx_add: crippled matrix");return; } + adjustsize(&x->m, row, col); + + buf=x->m.atombuffer+2; + + while(n--){ + buf->a_type = A_FLOAT; + buf++->a_w.w_float = atom_getfloat(ap++) + offset; + } + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_addscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc; + t_atom *m; + t_float offset = x->f; + adjustsize(&x->m, 1, argc); + m = x->m.atombuffer; + + while(n--){ + m->a_type = A_FLOAT; + (m++)->a_w.w_float = atom_getfloat(argv++) + offset; + } + outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer); +} + +static void mtx_add_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + t_atom *m; + t_atom *m1 = argv+2; + t_atom *m2 = x->m2.atombuffer+2; + int n = argc-2; + + if (argc<2){ post("mtx_add: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_add: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + + if (!(x->m2.col*x->m2.row)) { + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv); + return; + } + + if ((col!=x->m2.col)||(row!=x->m2.row)){ + post("mtx_add: matrix dimensions do not match"); + /* LATER SOLVE THIS */ + return; + } + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + t_float f = atom_getfloat(m1++)+atom_getfloat(m2++); + SETFLOAT(m, f); + m++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_add_float(t_mtx_binmtx *x, t_float f) +{ + t_matrix *m=&x->m, *m2=&x->m2; + t_atom *ap, *ap2=m2->atombuffer+2; + int row2, col2, n; + + if (!m2->atombuffer){ post("mulitply with what ?"); return; } + + row2=atom_getfloat(m2->atombuffer); + col2=atom_getfloat(m2->atombuffer+1); + adjustsize(m, row2, col2); + ap=m->atombuffer+2; + + n=row2*col2; + + while(n--){ + SETFLOAT(ap, f+atom_getfloat(ap2++)); + ap++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer); +} +static void *mtx_add_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc>1) post("mtx_add : extra arguments ignored"); + if (argc) { + t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_addscalar_class); + floatinlet_new(&x->x_obj, &x->f); + x->f = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, 0); + return(x); + } else { + t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_add_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + x->m.col = x->m.row = x->m2.col = x->m2.row = 0; + x->m.atombuffer = x->m2.atombuffer = 0; + return(x); + } +} + +static void mtx_add_setup(void) +{ + mtx_add_class = class_new(gensym("mtx_add"), (t_newmethod)mtx_add_new, (t_method)mtx_binmtx_free, + sizeof(t_mtx_binmtx), 0, A_GIMME, 0); + class_addcreator((t_newmethod)mtx_add_new, gensym("mtx_+"), A_GIMME,0); + class_addmethod(mtx_add_class, (t_method)mtx_add_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_add_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0); + class_addfloat (mtx_add_class, mtx_add_float); + class_addbang (mtx_add_class, mtx_binmtx_bang); + + mtx_addscalar_class = class_new(gensym("mtx_add"), 0, (t_method)mtx_binscalar_free, + sizeof(t_mtx_binscalar), 0, 0); + class_addcreator(0, gensym("mtx_+"), 0, 0); + class_addmethod(mtx_addscalar_class, (t_method)mtx_addscalar_matrix, gensym("matrix"), A_GIMME, 0); + class_addlist (mtx_addscalar_class, mtx_addscalar_list); + class_addbang (mtx_addscalar_class, mtx_binscalar_bang); + + class_sethelpsymbol(mtx_add_class, gensym("iemmatrix/mtx_binops")); + class_sethelpsymbol(mtx_addscalar_class, gensym("iemmatrix/mtx_binops")); +} + +/* mtx_sub */ +static t_class *mtx_sub_class, *mtx_subscalar_class; + +static void mtx_subscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc-2; + int row=atom_getfloat(argv), col=atom_getfloat(argv+1); + + t_float offset=x->f; + t_atom *buf; + t_atom *ap=argv+2; + + if(argc<2){post("mtx_sub: crippled matrix");return; } + adjustsize(&x->m, row, col); + + buf=x->m.atombuffer+2; + + while(n--){ + buf->a_type = A_FLOAT; + buf++->a_w.w_float = atom_getfloat(ap++) - offset; + } + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_subscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc; + t_atom *m; + t_float offset = x->f; + adjustsize(&x->m, 1, argc); + m = x->m.atombuffer; + + while(n--){ + m->a_type = A_FLOAT; + (m++)->a_w.w_float = atom_getfloat(argv++) - offset; + } + outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer); +} + +static void mtx_sub_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + t_atom *m; + t_atom *m1 = argv+2; + t_atom *m2 = x->m2.atombuffer+2; + int n = argc-2; + + if (argc<2){ post("mtx_sub: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_sub: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + + if (!(x->m2.col*x->m2.row)) { + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv); + return; + } + + if ((col!=x->m2.col)||(row!=x->m2.row)){ + post("mtx_sub: matrix dimensions do not match"); + /* LATER SOLVE THIS */ + return; + } + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + t_float f = atom_getfloat(m1++)-atom_getfloat(m2++); + SETFLOAT(m, f); + m++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_sub_float(t_mtx_binmtx *x, t_float f) +{ + t_matrix *m=&x->m, *m2=&x->m2; + t_atom *ap, *ap2=m2->atombuffer+2; + int row2, col2, n; + + if (!m2->atombuffer){ post("mulitply with what ?"); return; } + + row2=atom_getfloat(m2->atombuffer); + col2=atom_getfloat(m2->atombuffer+1); + adjustsize(m, row2, col2); + ap=m->atombuffer+2; + + n=row2*col2; + + while(n--){ + SETFLOAT(ap, f-atom_getfloat(ap2++)); + ap++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer); +} +static void *mtx_sub_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc>1) post("mtx_sub : extra arguments ignored"); + if (argc) { + t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_subscalar_class); + floatinlet_new(&x->x_obj, &x->f); + x->f = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, 0); + return(x); + } else { + t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_sub_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + x->m.col = x->m.row = x->m2.col = x->m2.row = 0; + x->m.atombuffer = x->m2.atombuffer = 0; + return(x); + } +} + +static void mtx_sub_setup(void) +{ + mtx_sub_class = class_new(gensym("mtx_sub"), (t_newmethod)mtx_sub_new, (t_method)mtx_binmtx_free, + sizeof(t_mtx_binmtx), 0, A_GIMME, 0); + class_addcreator((t_newmethod)mtx_sub_new, gensym("mtx_-"), A_GIMME,0); + class_addmethod(mtx_sub_class, (t_method)mtx_sub_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_sub_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0); + class_addfloat (mtx_sub_class, mtx_sub_float); + class_addbang (mtx_sub_class, mtx_binmtx_bang); + + mtx_subscalar_class = class_new(gensym("mtx_sub"), 0, (t_method)mtx_binscalar_free, + sizeof(t_mtx_binscalar), 0, 0); + class_addcreator(0, gensym("mtx_-"), 0, 0); + class_addmethod(mtx_subscalar_class, (t_method)mtx_subscalar_matrix, gensym("matrix"), A_GIMME, 0); + class_addlist (mtx_subscalar_class, mtx_subscalar_list); + class_addbang (mtx_subscalar_class, mtx_binscalar_bang); + + class_sethelpsymbol(mtx_sub_class, gensym("iemmatrix/mtx_binops")); + class_sethelpsymbol(mtx_subscalar_class, gensym("iemmatrix/mtx_binops")); +} + + +/* mtx_mul */ +static t_class *mtx_mul_class, *mtx_mulelement_class, *mtx_mulscalar_class; + +static void mtx_mul_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *m=&x->m, *m2=&x->m2; + t_atom *ap, *ap1=argv+2, *ap2=m2->atombuffer+2; + int row=atom_getfloat(argv), col=atom_getfloat(argv+1); + int row2, col2, n, r, c; + + if (!m2->atombuffer){ post("mulitply with what ?"); return; } + if (argc<2){ post("mtx_mul: crippled matrix"); return; } + if ((col<1)||(row<1)){post("mtx_mul: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + + row2=atom_getfloat(m2->atombuffer); + col2=atom_getfloat(m2->atombuffer+1); + + if (col!=row2) { post("mtx_mul: matrix dimensions do not match !"); return; } + + adjustsize(m, row, col2); + ap=m->atombuffer+2; + + for(r=0;r<row;r++) + for(c=0;c<col2;c++) { + t_matrixfloat sum = 0.f; + for(n=0;n<col;n++)sum+=(t_matrixfloat)atom_getfloat(ap1+col*r+n)*atom_getfloat(ap2+col2*n+c); + SETFLOAT(ap+col2*r+c,sum); + } + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer); +} + +static void mtx_mul_float(t_mtx_binmtx *x, t_float f) +{ + t_matrix *m=&x->m, *m2=&x->m2; + t_atom *ap, *ap2=m2->atombuffer+2; + int row2, col2, n; + + if (!m2->atombuffer){ post("mulitply with what ?"); return; } + + row2=atom_getfloat(m2->atombuffer); + col2=atom_getfloat(m2->atombuffer+1); + adjustsize(m, row2, col2); + ap=m->atombuffer+2; + + n=row2*col2; + + while(n--){ + SETFLOAT(ap, f*atom_getfloat(ap2++)); + ap++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer); +} + +static void mtx_mulelement_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; + t_atom *m2 = x->m2.atombuffer+2; + int n = argc-2; + + if (argc<2){ post("mtx_mul: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_mul: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + if (!(x->m2.col*x->m2.row)) { + adjustsize(&x->m, row, col); + matrix_set(&x->m, 0); + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); + return; + } + if ((col!=x->m2.col)||(row!=x->m2.row)){ post("matrix dimension do not match"); /* LATER SOLVE THIS */ return; } + + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + t_float f = atom_getfloat(argv++)*atom_getfloat(m2++); + SETFLOAT(m, f); + m++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} + +static void mtx_mulscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc-2; + t_atom *m; + t_float factor = x->f; + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + + if (argc<2){ + post("mtx_mul: crippled matrix"); + return; + } + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + m->a_type = A_FLOAT; + (m++)->a_w.w_float = atom_getfloat(argv++)*factor; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_mulscalar_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; + (m++)->a_w.w_float = atom_getfloat(argv++)*factor; + } + outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer); +} + +static void *mtx_mul_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc>1) post("mtx_mul : extra arguments ignored"); + if (argc) { + t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_mulscalar_class); + floatinlet_new(&x->x_obj, &x->f); + x->f = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, 0); + return(x); + } else { + if (s->s_name[4]=='.') { + /* element mul */ + + t_matrix *x = (t_matrix *)pd_new(mtx_mulelement_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + x->col = x->row = 0; + x->atombuffer = 0; + return(x); + } else { + t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_mul_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + x->m.col = x->m.row = x->m2.col = x->m2.row = 0; + x->m.atombuffer = x->m2.atombuffer = 0; + return (x); + } + } +} + +static void mtx_mul_setup(void) +{ + mtx_mul_class = class_new(gensym("mtx_mul"), (t_newmethod)mtx_mul_new, (t_method)mtx_binmtx_free, + sizeof(t_mtx_binmtx), 0, A_GIMME, 0); + class_addcreator((t_newmethod)mtx_mul_new, gensym("mtx_*"), A_GIMME,0); + class_addmethod(mtx_mul_class, (t_method)mtx_mul_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_mul_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0); + class_addfloat (mtx_mul_class, mtx_mul_float); + class_addbang (mtx_mul_class, mtx_binmtx_bang); + + mtx_mulelement_class = class_new(gensym("mtx_.*"), (t_newmethod)mtx_mul_new, (t_method)mtx_binmtx_free, + sizeof(t_mtx_binmtx), 0, A_GIMME, 0); + class_addmethod(mtx_mulelement_class, (t_method)mtx_mulelement_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_mulelement_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0); + class_addfloat (mtx_mulelement_class, mtx_mul_float); + class_addbang (mtx_mulelement_class, mtx_binmtx_bang); + + mtx_mulscalar_class = class_new(gensym("mtx_mul"), 0, (t_method)mtx_binscalar_free, + sizeof(t_mtx_binscalar), 0, 0); + class_addcreator(0, gensym("mtx_*"), 0, 0); + class_addcreator(0, gensym("mtx_.*"), 0, 0); + class_addmethod(mtx_mulscalar_class, (t_method)mtx_mulscalar_matrix, gensym("matrix"), A_GIMME, 0); + class_addlist (mtx_mulscalar_class, mtx_mulscalar_list); + class_addbang (mtx_mulscalar_class, mtx_binscalar_bang); + + class_sethelpsymbol(mtx_mul_class, gensym("iemmatrix/mtx_binops")); + class_sethelpsymbol(mtx_mulelement_class, gensym("iemmatrix/mtx_binops")); + class_sethelpsymbol(mtx_mulscalar_class, gensym("iemmatrix/mtx_binops")); +} + + +/* mtx_div */ +static t_class *mtx_divelement_class, *mtx_divscalar_class; + +static void mtx_divelement_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; + t_atom *m2 = x->m2.atombuffer+2; + int n = argc-2; + + if (argc<2){ post("mtx_div: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_div: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + if (!(x->m2.col*x->m2.row)) { + adjustsize(&x->m, row, col); + matrix_set(&x->m, 0); + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); + return; + } + if ((col!=x->m2.col)||(row!=x->m2.row)){ post("matrix dimension do not match"); /* LATER SOLVE THIS */ return; } + + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + t_float f = atom_getfloat(argv++)/atom_getfloat(m2++); + SETFLOAT(m, f); + m++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_divelement_float(t_mtx_binmtx *x, t_float f) +{ + t_matrix *m=&x->m, *m2=&x->m2; + t_atom *ap, *ap2=m2->atombuffer+2; + int row2, col2, n; + + if (!m2->atombuffer){ post("divide by what ?"); return; } + + row2=atom_getfloat(m2->atombuffer); + col2=atom_getfloat(m2->atombuffer+1); + adjustsize(m, row2, col2); + ap=m->atombuffer+2; + + n=row2*col2; + + while(n--){ + SETFLOAT(ap, f/atom_getfloat(ap2++)); + ap++; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer); +} +static void mtx_divscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc-2; + t_atom *m; + t_float factor = 1.0/x->f; + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + + if (argc<2){ + post("mtx_div: crippled matrix"); + return; + } + adjustsize(&x->m, row, col); + m = x->m.atombuffer+2; + + while(n--){ + m->a_type = A_FLOAT; + (m++)->a_w.w_float = atom_getfloat(argv++)*factor; + } + + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer); +} +static void mtx_divscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv) +{ + int n=argc; + t_atom *m; + t_float factor = 1.0/x->f; + + adjustsize(&x->m, 1, argc); + m = x->m.atombuffer; + + while(n--){ + m->a_type = A_FLOAT; + (m++)->a_w.w_float = atom_getfloat(argv++)*factor; + } + + outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer); +} + +static void *mtx_div_new(t_symbol *s, int argc, t_atom *argv) +{ + if (argc>1) post("mtx_div : extra arguments ignored"); + if (argc) { + /* scalar division */ + t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_divscalar_class); + floatinlet_new(&x->x_obj, &x->f); + x->f = atom_getfloatarg(0, argc, argv); + outlet_new(&x->x_obj, 0); + return(x); + } else { + /* element division */ + t_matrix *x = (t_matrix *)pd_new(mtx_divelement_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + x->col = x->row = 0; + x->atombuffer = 0; + return(x); + } +} + +static void mtx_div_setup(void) +{ + mtx_divelement_class = class_new(gensym("mtx_./"), (t_newmethod)mtx_div_new, (t_method)mtx_binmtx_free, + sizeof(t_mtx_binmtx), 0, A_GIMME, 0); + class_addmethod(mtx_divelement_class, (t_method)mtx_divelement_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_divelement_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0); + class_addfloat (mtx_divelement_class, mtx_divelement_float); + class_addbang (mtx_divelement_class, mtx_binmtx_bang); + + mtx_divscalar_class = class_new(gensym("mtx_./"), 0, (t_method)mtx_binscalar_free, + sizeof(t_mtx_binscalar), 0, 0); + class_addmethod(mtx_divscalar_class, (t_method)mtx_divscalar_matrix, gensym("matrix"), A_GIMME, 0); + class_addlist (mtx_divscalar_class, mtx_divscalar_list); + class_addbang (mtx_divscalar_class, mtx_binscalar_bang); + + class_sethelpsymbol(mtx_divelement_class, gensym("iemmatrix/mtx_binops")); + class_sethelpsymbol(mtx_divscalar_class, gensym("iemmatrix/mtx_binops")); +} + +void mtx_binops_setup(void) +{ + mtx_add_setup(); + mtx_sub_setup(); + mtx_mul_setup(); + mtx_div_setup(); +} +void iemtx_binops_setup(void) +{ + mtx_binops_setup(); +} diff --git a/src/mtx_check.c b/src/mtx_check.c new file mode 100644 index 0000000..0e2eda1 --- /dev/null +++ b/src/mtx_check.c @@ -0,0 +1,76 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_check */ +static t_class *mtx_check_class; + +static void mtx_check_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + t_atom *ap; + int length=row*col, n; + argc-=2; + + if(length>argc) { + /* sparse matrix */ + adjustsize(x, row, col); + matrix_set(x, 0); + argv+=2; + ap=x->atombuffer+2; + n=argc; + while(n--){ + t_float f = atom_getfloat(argv++); + SETFLOAT(ap, f); + ap++; + } + matrix_bang(x); + } else { + SETFLOAT(argv, row); + SETFLOAT(argv+1, col); + ap=argv+2; + n=length; + while(n--){ + t_float f = atom_getfloat(ap); + SETFLOAT(ap, f); + ap++; + } + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), length+2, argv); + } +} + +static void *mtx_check_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_check_class); + outlet_new(&x->x_obj, 0); + x->col=x->row=0; + x->atombuffer=0; + return (x); +} + +void mtx_check_setup(void) +{ + mtx_check_class = class_new(gensym("mtx_check"), (t_newmethod)mtx_check_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_check_class, matrix_bang); + class_addmethod(mtx_check_class, (t_method)mtx_check_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_check_class, gensym("iemmatrix/matrix")); +} + + +void iemtx_check_setup(void) +{ + mtx_check_setup(); +} diff --git a/src/mtx_col.c b/src/mtx_col.c new file mode 100644 index 0000000..1ee3dbb --- /dev/null +++ b/src/mtx_col.c @@ -0,0 +1,129 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_col */ +static t_class *mtx_col_class; + +static void mtx_col_float(t_matrix *x, t_floatarg f) +{ + int i = f; + if(i<0)i=0; + x->current_col = i; +} +static void mtx_col_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + if (argc<2){ post("matrix : corrupt matrix passed"); return; } + row = atom_getfloat(argv); + col = atom_getfloat(argv+1); + if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; } + if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; } + matrix_matrix2(x, s, argc, argv); + matrix_bang(x); +} +static void mtx_col_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + if (argc==1){ + t_float f=atom_getfloat(argv); + t_atom *ap=x->atombuffer+1+x->current_col; + if (x->current_col>x->col){ + post("mtx_col : too high a column is to be set"); + return; + } + if (x->current_col){ + int n=x->row; + while(n--){ + SETFLOAT(ap, f); + ap+=x->row+1; + } + } + matrix_bang(x); + return; + } + + if (argc<x->row){ + post("mtx_col : column length is too small for %dx%d-matrix", x->row, x->col); + return; + } + if (x->current_col>x->col){ + post("mtx_col : too high a column is to be set"); + return; + } + if(x->current_col) { + int r=x->row; + t_atom *ap=x->atombuffer+1+x->current_col; + while(r--)SETFLOAT(&ap[(x->row-r-1)*x->col], atom_getfloat(argv++)); + } else { + int r=x->row; + t_atom *ap=x->atombuffer+2; + while (r--) { + t_float f=atom_getfloat(argv++); + int c=x->col; + while(c--){ + SETFLOAT(ap, f); + ap++; + } + } + } + matrix_bang(x); +} +static void *mtx_col_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_col_class); + int i, j, q; + outlet_new(&x->x_obj, 0); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + x->current_col=0; + x->col=x->row=0; + x->atombuffer=0; + switch (argc) { + case 0:break; + case 1: + i = atom_getfloat(argv); + if (i<0)i=0; + if(i)adjustsize(x, i, i); + matrix_set(x, 0); + break; + case 2: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + break; + default: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + q = atom_getfloat(argv++);if(q<0)q=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + x->current_col=q; + } + return (x); +} +void mtx_col_setup(void) +{ + mtx_col_class = class_new(gensym("mtx_col"), (t_newmethod)mtx_col_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_col_class, matrix_bang); + class_addlist (mtx_col_class, mtx_col_list); + class_addmethod(mtx_col_class, (t_method)mtx_col_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_col_class, (t_method)mtx_col_float, gensym(""), A_FLOAT, 0); + class_sethelpsymbol(mtx_col_class, gensym("iemmatrix/mtx_element")); +} + +void iemmtx_col_setup(void) +{ + mtx_col_setup(); +} diff --git a/src/mtx_diag.c b/src/mtx_diag.c new file mode 100644 index 0000000..65acff2 --- /dev/null +++ b/src/mtx_diag.c @@ -0,0 +1,59 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_diag */ +static t_class *mtx_diag_class; +static void mtx_diag_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + int length=(col<row)?col:row, n=length; + t_atom *ap = (t_atom *)getbytes(length * sizeof(t_atom)), *dummy=ap; + if(row*col>argc-2)post("mtx_diag: sparse matrices not yet supported : use \"mtx_check\""); + else { + for(n=0;n<length;n++, dummy++)SETFLOAT(dummy, atom_getfloat(argv+n*(col+1))); + outlet_list(x->x_obj.ob_outlet, gensym("diag"), length, ap); + } + freebytes(ap, (length * sizeof(t_atom))); +} + +static void *mtx_diag_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_diag_class); + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + + if(!argc)return(x); + x->atombuffer = (t_atom *)getbytes((argc*argc+2)*sizeof(t_atom)); + setdimen(x, argc, argc); + matrix_set(x, 0); + argv+=argc-1; + while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+x->col), atom_getfloat(argv--)); + + return (x); +} +void mtx_diag_setup(void) +{ + mtx_diag_class = class_new(gensym("mtx_diag"), (t_newmethod)mtx_diag_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist (mtx_diag_class, matrix_diag); + class_addbang (mtx_diag_class, matrix_bang); + class_addmethod(mtx_diag_class, (t_method)mtx_diag_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_diag_class, gensym("iemmatrix/mtx_trace")); +} +void iemtx_diag_setup(void){ + void mtx_diag_setup(void); +} diff --git a/src/mtx_diegg.c b/src/mtx_diegg.c new file mode 100644 index 0000000..658471f --- /dev/null +++ b/src/mtx_diegg.c @@ -0,0 +1,56 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" +static t_class *mtx_diegg_class; +static void mtx_diegg_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + int length=(col<row)?col:row, n=length; + t_atom *ap = (t_atom *)getbytes(length * sizeof(t_atom)), *dummy=ap; + if(row*col>argc-2)post("mtx_diegg: sparse matrices not yet supported : use \"mtx_check\""); + else { + for(n=0;n<length;n++, dummy++)SETFLOAT(dummy, atom_getfloat(argv+(n-1)*(col-1))); + outlet_list(x->x_obj.ob_outlet, gensym("diegg"), length, ap); + } + freebytes(ap, (length * sizeof(t_atom))); +} +static void *mtx_diegg_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_diegg_class); + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + + if(!argc)return(x); + x->atombuffer = (t_atom *)getbytes((argc*argc+2)*sizeof(t_atom)); + setdimen(x, argc, argc); + matrix_set(x, 0); + argv+=argc-1; + while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+x->col), atom_getfloat(argv--)); + + return (x); +} +void mtx_diegg_setup(void) +{ + mtx_diegg_class = class_new(gensym("mtx_diegg"), (t_newmethod)mtx_diegg_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist (mtx_diegg_class, matrix_diegg); + class_addbang (mtx_diegg_class, matrix_bang); + class_addmethod(mtx_diegg_class, (t_method)mtx_diegg_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_diegg_class, gensym("iemmatrix/mtx_special")); +} +void iemtx_diegg_setup(void){ + mtx_diegg_setup(); +} diff --git a/src/mtx_egg.c b/src/mtx_egg.c new file mode 100644 index 0000000..a44894c --- /dev/null +++ b/src/mtx_egg.c @@ -0,0 +1,58 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_egg */ +static t_class *mtx_egg_class; +static void *mtx_egg_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_egg_class); + int col=0, row=0; + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + switch(argc) { + case 0: + break; + case 1: + col=row=atom_getfloat(argv); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + } + if(col<0)col=0; + if(row<0)row=0; + if (col*row){ + int n = (col<row)?col:row; + x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom)); + setdimen(x, row, col); + matrix_set(x, 0); + while(n--)SETFLOAT(x->atombuffer+2+(n+1)*(col-1), 1); + } + return (x); +} +void mtx_egg_setup(void) +{ + mtx_egg_class = class_new(gensym("mtx_egg"), (t_newmethod)mtx_egg_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist(mtx_egg_class, matrix_egg); + class_addbang(mtx_egg_class, matrix_bang); + class_addmethod(mtx_egg_class, (t_method)matrix_egg, gensym("matrix"), A_GIMME, 0); + + class_sethelpsymbol(mtx_egg_class, gensym("iemmatrix/mtx_special")); +} +void iemtx_egg_setup(void){ + mtx_egg_setup(); +} diff --git a/src/mtx_element.c b/src/mtx_element.c new file mode 100644 index 0000000..10d9664 --- /dev/null +++ b/src/mtx_element.c @@ -0,0 +1,118 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + + +/* mtx_element */ +static t_class *mtx_element_class; + +static void mtx_element_list2(t_matrix *x, t_floatarg f1, t_floatarg f2) +{ + int r = f1, c= f2; + if(r<0)r=0; + if(c<0)c=0; + x->current_row = r; + x->current_col = c; +} +static void mtx_element_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + if (argc<2){ post("matrix : corrupt matrix passed"); return; } + row = atom_getfloat(argv); + col = atom_getfloat(argv+1); + if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; } + if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; } + matrix_matrix2(x, s, argc, argv); + matrix_bang(x); +} +static void mtx_element_float(t_matrix *x, t_floatarg f) +{ + if(x->current_col>x->col || x->current_row>x->row){ + error("mtx_element: element position exceeds matrix dimensions"); + return; + } + if(x->current_row == 0 && x->current_col == 0){ + matrix_set(x, f); + matrix_bang(x); + return; + } + if(x->current_row*x->current_col)SETFLOAT(x->atombuffer+1+(x->current_row-1)*x->col+x->current_col, f); + else { + t_atom *ap=x->atombuffer+2; + int count; + if (!x->current_col){ + ap+=x->col*(x->current_row-1); + count=x->col; + while(count--)SETFLOAT(&ap[count], f); + } else { // x->current_row==0 + ap+=x->current_col-1; + count=x->row; + while(count--)SETFLOAT(&ap[count*x->col], f); + } + } + matrix_bang(x); +} + +static void *mtx_element_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_element_class); + int i, j, q; + outlet_new(&x->x_obj, 0); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + x->current_row=x->current_col=0; + x->col=x->row=0; + x->atombuffer=0; + switch (argc) { + case 1: + i = atom_getfloat(argv); + if (i<0)i=0; + if(i)adjustsize(x, i, i); + matrix_set(x, 0); + break; + case 2: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + break; + case 4: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + q = atom_getfloat(argv++);if(q<0)q=0; + x->current_row=q; + q = atom_getfloat(argv++);if(q<0)q=0; + x->current_col=q; + break; + default:; + } + return (x); +} +void mtx_element_setup(void) +{ + mtx_element_class = class_new(gensym("mtx_element"), (t_newmethod)mtx_element_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_element_class, matrix_bang); + class_addfloat (mtx_element_class, mtx_element_float); + class_addmethod(mtx_element_class, (t_method)mtx_element_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_element_class, (t_method)mtx_element_list2, gensym(""), A_FLOAT, A_FLOAT, 0); + class_sethelpsymbol(mtx_element_class, gensym("iemmatrix/mtx_element")); +} + + +void iemmtx_element_setup(void) +{ + mtx_element_setup(); +} diff --git a/src/mtx_eye.c b/src/mtx_eye.c new file mode 100644 index 0000000..e416ac4 --- /dev/null +++ b/src/mtx_eye.c @@ -0,0 +1,60 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* ------------------------------------------------------------------------------------- */ + +/* mtx_eye */ +static t_class *mtx_eye_class; +static void *mtx_eye_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_eye_class); + int col=0, row=0; + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + switch(argc) { + case 0: + break; + case 1: + col=row=atom_getfloat(argv); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + } + if(col<0)col=0; + if(row<0)row=0; + if (col*row){ + int n = (col<row)?col:row; + x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom)); + setdimen(x, row, col); + matrix_set(x, 0); + while(n--)SETFLOAT(x->atombuffer+2+n*(1+col), 1); + } + return (x); +} +void mtx_eye_setup(void) +{ + mtx_eye_class = class_new(gensym("mtx_eye"), (t_newmethod)mtx_eye_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist(mtx_eye_class, matrix_eye); + class_addbang(mtx_eye_class, matrix_bang); + class_addmethod(mtx_eye_class, (t_method)matrix_eye, gensym("matrix"), A_GIMME, 0); + + class_sethelpsymbol(mtx_eye_class, gensym("iemmatrix/mtx_special")); +} +void iemtx_eye_setup(void){ + mtx_eye_setup(); +} diff --git a/src/mtx_inverse.c b/src/mtx_inverse.c new file mode 100644 index 0000000..400f734 --- /dev/null +++ b/src/mtx_inverse.c @@ -0,0 +1,118 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_inverse */ +static t_class *mtx_inverse_class; + +static void mtx_inverse_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + /* maybe we should do this in double or long double ? */ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + int i, k, row2=row*row; + + t_matrixfloat *original, *inverted; + t_matrixfloat *a1, *a2, *b1, *b2; // dummy pointers + + int ok = 0; + + if(row*col+2>argc){ + post("mtx_print : sparse matrices not yet supported : use \"mtx_check\""); + return; + } + if (row!=col){ + post("mtx_inverse: only square matrices can be inverted"); + return; + } + + // reserve memory for outputting afterwards + adjustsize(x, row, row); + // 1. get the 2 matrices : orig; invert (create as eye, but will be orig^(-1)) + inverted = (t_matrixfloat *)getbytes(sizeof(t_matrixfloat)*row2); + // 1a extract values of A to float-buf + original=matrix2float(argv); + // 1b make an eye-shaped float-buf for B + i=row2; + b1=inverted; + while(i--)*b1++=0; + i=row; + b1=inverted; + while(i--)b1[i*(row+1)]=1; + + // 2. do the Gauss-Jordan + for (k=0;k<row;k++) { + // 2. adjust current row + t_matrixfloat diagel = original[k*(col+1)]; + t_matrixfloat i_diagel = diagel?1./diagel:0; + if (!diagel)ok++; + + + /* normalize current row (set the diagonal-element to 1 */ + a2=original+k*col; + b2=inverted+k*col; + i=row; + while(i--){ + *a2++*=i_diagel; + *b2++*=i_diagel; + } + /* eliminate the k-th element in each row by adding the weighted normalized row */ + + a2=original+k*row; + b2=inverted+k*row; + for(i=0;i<row;i++) + if (i-k) { + t_matrixfloat f=-*(original+i*row+k); + int j = row; + a1=original+i*row; + b1=inverted+i*row; + while (j--) { + *(a1+j)+=f**(a2+j); + *(b1+j)+=f**(b2+j); + } + } + } + // 3. output the matrix + // 3a convert the floatbuf to an atombuf; + float2matrix(x->atombuffer, inverted); + // 3b destroy the buffers + freebytes(original, sizeof(t_matrixfloat)*row2); + + if (ok)post("mtx_inverse: couldn't really invert the matrix !!! %d error%c", ok, (ok-1)?'s':0); + + // 3c output the atombuf; + matrix_bang(x); +} + +static void *mtx_inverse_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_inverse_class); + outlet_new(&x->x_obj, 0); + x->col=x->row=0; + x->atombuffer=0; + + return (x); +} +void mtx_inverse_setup(void) +{ + mtx_inverse_class = class_new(gensym("mtx_inverse"), (t_newmethod)mtx_inverse_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_inverse_class, matrix_bang); + class_addmethod(mtx_inverse_class, (t_method)mtx_inverse_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_inverse_class, gensym("iemmatrix/mtx_inverse")); +} + +void iemtx_inverse_setup(void){ + mtx_inverse_setup(); +} diff --git a/src/mtx_matrix.c b/src/mtx_matrix.c new file mode 100644 index 0000000..98df0d2 --- /dev/null +++ b/src/mtx_matrix.c @@ -0,0 +1,606 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ + +/* + matrix : basic object : create and store matrices + mtx : alias for matrix +*/ + +#include "iemmatrix.h" + +/* -------------------- matrix ------------------------------ */ + +static t_class *matrix_class; + +/* intern utility functions */ + +void setdimen(t_matrix *x, int row, int col) +{ + x->col = col; + x->row = row; + SETFLOAT(x->atombuffer, row); + SETFLOAT(x->atombuffer+1, col); +} + +void adjustsize(t_matrix *x, int desiredRow, int desiredCol) +{ + int col=x->col, row=x->row; + + if (desiredRow<1){ + post("cannot make less than 1 rows"); + desiredRow=1; + } + if (desiredCol<1){ + post("cannot make less than 1 columns"); + desiredCol=1; + } + + if (col*row!=desiredRow*desiredCol){ + if(x->atombuffer)freebytes(x->atombuffer, (col*row+2)*sizeof(t_atom)); + x->atombuffer=(t_atom *)getbytes((desiredCol*desiredRow+2)*sizeof(t_atom)); + } + + setdimen(x, desiredRow, desiredCol); + return; +} + +void debugmtx(int argc, t_float *buf, int id) +{ + int i=argc; + while(i--){ + int j=argc; + startpost("debug%d: ", id); + while(j--) + startpost("%f ", *buf++); + endpost(); + } +} +t_matrixfloat *matrix2float(t_atom *ap) +{ + int row = atom_getfloat(ap++); + int col=atom_getfloat(ap++); + int length = row * col; + t_matrixfloat *buffer = (t_matrixfloat *)getbytes(sizeof(t_matrixfloat)*length); + t_matrixfloat *buf = buffer; + while(length--)*buf++=atom_getfloat(ap++); + return buffer; +} +void float2matrix(t_atom *ap, t_matrixfloat *buffer) +{ + int row=atom_getfloat(ap++); + int col=atom_getfloat(ap++); + int length = row * col; + t_matrixfloat*buf= buffer; + while(length--){ + SETFLOAT(ap, *buf++); + ap++; + } + freebytes(buffer, row*col*sizeof(t_matrixfloat)); +} + +/* core functions */ +void matrix_bang(t_matrix *x) +{ + /* output the matrix */ + if (x->atombuffer)outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->col*x->row+2, x->atombuffer); +} + +void matrix_matrix2(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + + if (argc<2){ + post("matrix : corrupt matrix passed"); + return; + } + row = atom_getfloat(argv); + col = atom_getfloat(argv+1); + if ((row<1)||(col<1)){ + post("matrix : corrupt matrix passed"); + return; + } + if (row*col > argc-2){ + post("matrix: sparse matrices not yet supported : use \"mtx_check\""); + return; + } + + /* this is fast and dirty, MAYBE make it slow and clean */ + /* or, to clean matrices, use the mtx_check object */ + if (row*col != x->row*x->col) { + freebytes(x->atombuffer, x->row*x->col*sizeof(t_atom)); + x->atombuffer = copybytes(argv, (row*col+2)*sizeof(t_atom)); + } else memcpy(x->atombuffer, argv, (row*col+2)*sizeof(t_atom)); + + setdimen(x, row, col); +} + +static void matrix_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + + if (argc<2){ + post("matrix : corrupt matrix passed"); + return; + } + row = atom_getfloat(argv); + col = atom_getfloat(argv+1); + if ((row<1)||(col<1)){ + post("matrix : corrupt matrix passed"); + return; + } + if (row*col > argc-2){ + post("matrix: sparse matrices not yet supported : use \"mtx_check\""); + return; + } + + matrix_matrix2(x, s, argc, argv); + matrix_bang(x); +} + + +/* basic functions */ + +void matrix_set(t_matrix *x, t_float f) +{ + int size = x->col * x->row; + t_atom *buf=x->atombuffer+2; + if(x->atombuffer)while(size--)SETFLOAT(&buf[size], f); +} + +void matrix_zeros(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row; + + switch(argc) { + case 0: /* zero out the actual matrix */ + matrix_set(x, 0); + break; + case 1: + row=atom_getfloat(argv); + adjustsize(x, row, row); + matrix_set(x, 0); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + adjustsize(x, row, col); + + matrix_set(x, 0); + } + + matrix_bang(x); +} + +void matrix_ones(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row; + + switch(argc) { + case 0: /* zero out the actual matrix */ + matrix_set(x, 1); + break; + case 1: + row=atom_getfloat(argv); + adjustsize(x, row, row); + matrix_set(x, 1); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + adjustsize(x, row, col); + + matrix_set(x, 1); + } + + matrix_bang(x); +} + +void matrix_eye(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row; + int n; + + switch(argc) { + case 0: /* zero out the actual matrix */ + matrix_set(x, 0); + break; + case 1: + row=atom_getfloat(argv); + adjustsize(x, row, row); + matrix_set(x, 0); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + adjustsize(x, row, col); + matrix_set(x, 0); + } + + col=x->col; + row=x->row; + n = (col<row)?col:row; + while(n--)SETFLOAT(x->atombuffer+2+n*(1+col), 1); + + matrix_bang(x); +} +void matrix_egg(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row; + int n; + + switch(argc) { + case 0: /* zero out the actual matrix */ + matrix_set(x, 0); + break; + case 1: + row=atom_getfloat(argv); + adjustsize(x, row, row); + matrix_set(x, 0); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + adjustsize(x, row, col); + matrix_set(x, 0); + } + + col=x->col; + row=x->row; + n = (col<row)?col:row; + while(n--)SETFLOAT(x->atombuffer+2+(n+1)*(col-1), 1); + + matrix_bang(x); +} + +void matrix_diag(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col=argc; + argv+=argc-1; + if (argc<1) { + post("matrix: no diagonale present"); + return; + } + adjustsize(x, argc, argc); + matrix_set(x, 0); + + while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+col), atom_getfloat(argv--)); + + matrix_bang(x); +} +void matrix_diegg(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col=argc; + argv+=argc-1; + if (argc<1) { + post("matrix: no dieggonale present"); + return; + } + adjustsize(x, argc, argc); + matrix_set(x, 0); + + while(argc--){ + t_atom *ap=x->atombuffer+2+(argc+1)*(col-1); + SETFLOAT(ap, atom_getfloat(argv--)); + } + + matrix_bang(x); +} +/* the rest */ + +void matrix_row(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *ap; + int row=x->row, col=x->col; + int r; + t_float f; + + switch (argc){ + case 0: + for (r=0;r<row;r++)outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer+r*col+2); + break; + case 1: + r=atom_getfloat(argv)-1; + if ((r<0)||(r>=row)){ + post("matrix: row index %d is out of range", r+1); + return; + } + outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer+r*col+2); + break; + case 2: + r=atom_getfloat(argv)-1; + f=atom_getfloat(argv+1); + if ((r<0)||(r>=row)){ + post("matrix: row index %d is out of range", r+1); + return; + } + + + default: + r=atom_getfloat(argv++)-1; + if (argc--<col){ + post("matrix: sparse rows not yet supported : use \"mtx_check\""); + return; + } + if ((r<0)||(r>=row)){ + post("matrix: row index %d is out of range", r+1); + return; + } + if (r==row) { + } else { + ap=x->atombuffer+2+col*r; + memcpy(ap, argv, col*sizeof(t_atom)); + } + } +} + +void matrix_col(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *ap; + int row=x->row, col=x->col; + int c, r; + + switch (argc){ + case 0: + ap=(t_atom *)getbytes(row*sizeof(t_atom)); + for (c=0;c<col;c++) { + for (r=0;r<row;r++)SETFLOAT(&ap[r], atom_getfloat(x->atombuffer+2+c+col*r)); + outlet_list(x->x_obj.ob_outlet, gensym("col"), row, ap); + } + freebytes(ap, row*sizeof(t_atom)); + break; + case 1: + ap=(t_atom *)getbytes(row*sizeof(t_atom)); + c=atom_getfloat(argv)-1; + if ((c<0)||(c>=col)){ + post("matrix: col index %d is out of range", c+1); + return; + } + for (r=0;r<row;r++)SETFLOAT(&ap[r], atom_getfloat(x->atombuffer+2+c+col*r)); + outlet_list(x->x_obj.ob_outlet, gensym("col"), row, ap); + freebytes(ap, row*sizeof(t_atom)); + break; + default: + c=atom_getfloat(argv++)-1; + if (argc--<row){ + post("matrix: sparse cols not yet supported : use \"mtx_check\""); + return; + } + if ((c<0)||(c>=col)){ + post("matrix: col index %d is out of range", c+1); + return; + } + argv+=argc-1; + if (argc>row)argc=row; + while(argc--){ + ap=x->atombuffer+2+c+col*argc; + SETFLOAT(ap, atom_getfloat(argv--)); + } + } +} + +void matrix_element(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *ap=x->atombuffer+2; + int row=x->row, col=x->col; + int r, c, i=row*col; + + switch (argc){ + case 0: + while(i--)outlet_float(x->x_obj.ob_outlet, atom_getfloat(ap++)); + break; + case 1: + r=c=atom_getfloat(argv)-1; + if ((r<0)||(r>=row)){ + post("matrix: row index %d is out of range", r+1); + return; + } + if ((c<0)||(c>=col)){ + post("matrix: col index %d is out of range", c+1); + return; + } + outlet_float(x->x_obj.ob_outlet, atom_getfloat(x->atombuffer+2+c+r*col)); + break; + case 2: + r=atom_getfloat(argv++)-1; + c=atom_getfloat(argv++)-1; + if ((r<0)||(r>=row)){ post("matrix: row index %d is out of range", r+1); return; } + if ((c<0)||(c>=col)){ post("matrix: col index %d is out of range", c+1); return; } + outlet_float(x->x_obj.ob_outlet, atom_getfloat(x->atombuffer+2+c+r*col)); + break; + default: + r=atom_getfloat(argv++)-1; + c=atom_getfloat(argv++)-1; + if ((r<0)||(r>=row)){ post("matrix: row index %d is out of range", r+1); return; } + if ((c<0)||(c>=col)){ post("matrix: col index %d is out of range", c+1); return; } + SETFLOAT(x->atombuffer+2+c+r*col, atom_getfloat(argv)); + } +} + +static void matrix_float(t_matrix *x, t_float f) +{ + matrix_set(x, f); + matrix_bang(x); +} + +/* ------------- file I/O ------------------ */ + +static void matrix_read(t_matrix *x, t_symbol *filename) +{ + t_binbuf *bbuf = binbuf_new(); + t_atom *ap; + int n; + + if (binbuf_read_via_path(bbuf, filename->s_name, canvas_getdir(x->x_canvas)->s_name, 0)) + error("matrix: failed to read %s", filename->s_name); + + ap=binbuf_getvec(bbuf); + n =binbuf_getnatom(bbuf)-1; + + if ((ap->a_type == A_SYMBOL) && + (!strcmp(ap->a_w.w_symbol->s_name,"matrix") || !strcmp(ap->a_w.w_symbol->s_name,"#matrix")) ){ + matrix_matrix2(x, gensym("matrix"), n, ap+1); + } + + binbuf_free(bbuf); +} +static void matrix_write(t_matrix *x, t_symbol *filename) +{ + t_atom *ap=x->atombuffer+2; + char filnam[MAXPDSTRING]; + int rows = x->row, cols = x->col; + FILE *f=0; + + sys_bashfilename(filename->s_name, filnam); + + /* open file */ + if (!(f = fopen(filnam, "w"))) { + error("matrix : failed to open %s", filnam); + } else { + char *text=(char *)getbytes(sizeof(char)*MAXPDSTRING); + int textlen; + + /* header: + * we now write "#matrix" instead of "matrix", + * so that these files can easily read by other + * applications such as octave + */ + sprintf(text, "#matrix %d %d\n", rows, cols); + textlen = strlen(text); + if (fwrite(text, textlen*sizeof(char), 1, f) < 1) { + error("matrix : failed to write %s", filnam); goto end; + } + + while(rows--) { + int c = cols; + while (c--) { + t_float val = atom_getfloat(ap++); + sprintf(text, "%.15f ", val); + textlen=strlen(text); + if (fwrite(text, textlen*sizeof(char), 1, f) < 1) { + error("matrix : failed to write %s", filnam); goto end; + } + } + if (fwrite("\n", sizeof(char), 1, f) < 1) { + error("matrix : failed to write %s", filnam); goto end; + } + } + freebytes(text, sizeof(char)*MAXPDSTRING); + } + + end: + /* close file */ + if (f) fclose(f); +} + +void matrix_free(t_matrix *x) +{ + freebytes(x->atombuffer, (x->col*x->row+2)*sizeof(t_atom)); + x->atombuffer=0; + x->col=x->row=0; +} +static void matrix_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + /* like matrix, but without col/row information, so the previous size is kept */ + int row=x->row, col=x->col; + + if(!row*col){ + post("matrix : unknown matrix dimensions"); + return; + } + if (argc<row*col){ + post("matrix: sparse matrices not yet supported : use \"mtx_check\" !"); + return; + } + + memcpy(x->atombuffer+2, argv, row*col*sizeof(t_atom)); + matrix_bang(x); +} + +static void *matrix_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(matrix_class); + int row, col; + + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + outlet_new(&x->x_obj, 0); + + x->atombuffer = 0; + x->x_canvas = canvas_getcurrent(); + + switch (argc) { + case 0: + row = col = 0; + break; + case 1: + if (argv->a_type == A_SYMBOL) { + matrix_read(x, argv->a_w.w_symbol); + return(x); + } + row = col = atom_getfloat(argv); + break; + default: + row = atom_getfloat(argv++); + col = atom_getfloat(argv++); + } + + if(row*col){ + adjustsize(x, row, col); + matrix_set(x, 0); + } + + return (x); +} + +void matrix_setup(void) +{ + matrix_class = class_new(gensym("matrix"), (t_newmethod)matrix_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addcreator((t_newmethod)matrix_new, gensym("mtx"), A_GIMME, 0); + + /* the core : functions for matrices */ + class_addmethod (matrix_class, (t_method)matrix_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_matrix2, gensym(""), A_GIMME, 0); + + /* the basics : functions for creation */ + class_addmethod (matrix_class, (t_method)matrix_eye, gensym("eye"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_diag, gensym("diag"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_ones, gensym("ones"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_zeros, gensym("zeros"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_egg, gensym("egg"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_diegg, gensym("diegg"), A_GIMME, 0); + + /* the rest : functions for anything */ + class_addbang (matrix_class, matrix_bang); + class_addfloat (matrix_class, matrix_float); + class_addlist (matrix_class, matrix_list); + class_addmethod (matrix_class, (t_method)matrix_row, gensym("row"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_col, gensym("column"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_col, gensym("col"), A_GIMME, 0); + class_addmethod (matrix_class, (t_method)matrix_element, gensym("element"), A_GIMME, 0); + + /* the file functions */ + class_addmethod (matrix_class, (t_method)matrix_write, gensym("write"), A_SYMBOL, 0); + class_addmethod (matrix_class, (t_method)matrix_read , gensym("read") , A_SYMBOL, 0); + + class_sethelpsymbol(matrix_class, gensym("iemmatrix/matrix")); +} + +void iemmtx_matrix_setup(void){ + matrix_setup(); +} + +void mtx_matrix_setup(void){ + matrix_setup(); +} diff --git a/src/mtx_mean.c b/src/mtx_mean.c new file mode 100644 index 0000000..bb0d870 --- /dev/null +++ b/src/mtx_mean.c @@ -0,0 +1,61 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + + +/* mtx_mean */ +static t_class *mtx_mean_class; + +static void mtx_mean_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + t_atom *ip, *op; + int c=col, r; + t_float sum; + t_float factor=1./row; + adjustsize(x, 1, col); + op=x->atombuffer; + + while(c--){ + sum=0; + ip=argv+col-c-1; + r=row; + while(r--)sum+=atom_getfloat(ip+col*r); + SETFLOAT(op, sum*factor); + op++; + } + outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer); +} + +static void *mtx_mean_new(void) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_mean_class); + outlet_new(&x->x_obj, 0); + x->col=x->row=0; + x->atombuffer=0; + return (x); +} +void mtx_mean_setup(void) +{ + mtx_mean_class = class_new(gensym("mtx_mean"), (t_newmethod)mtx_mean_new, + (t_method)matrix_free, sizeof(t_matrix), 0, 0, 0); + class_addmethod(mtx_mean_class, (t_method)mtx_mean_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_mean_class, gensym("iemmatrix/mtx_mean")); +} + +void iemtx_mean_setup(void) +{ + mtx_mean_setup(); +} diff --git a/src/mtx_ones.c b/src/mtx_ones.c new file mode 100644 index 0000000..c3dccf5 --- /dev/null +++ b/src/mtx_ones.c @@ -0,0 +1,56 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_ones */ +static t_class *mtx_ones_class; +static void *mtx_ones_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_ones_class); + int col=0, row=0; + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + switch(argc) { + case 0: + break; + case 1: + col=row=atom_getfloat(argv); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + } + if(col<0)col=0; + if(row<0)row=0; + if (col*row){ + x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom)); + setdimen(x, row, col); + matrix_set(x, 1); + } + return (x); +} +void mtx_ones_setup(void) +{ + mtx_ones_class = class_new(gensym("mtx_ones"), (t_newmethod)mtx_ones_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist(mtx_ones_class, matrix_ones); + class_addbang(mtx_ones_class, matrix_bang); + class_addmethod(mtx_ones_class, (t_method)matrix_ones, gensym("matrix"), A_GIMME, 0); + + class_sethelpsymbol(mtx_ones_class, gensym("iemmatrix/mtx_special")); +} +void iemtx_ones_setup(void){ + mtx_ones_setup(); +} diff --git a/src/mtx_pivot.c b/src/mtx_pivot.c new file mode 100644 index 0000000..1ac4804 --- /dev/null +++ b/src/mtx_pivot.c @@ -0,0 +1,171 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + + +/* mtx_pivot */ +static t_class *mtx_pivot_class; + +typedef struct _mtx_pivot +{ + t_object x_obj; + + t_matrix m; // the output matrix + t_matrix m_pre; // the pre -multiply matrix + t_matrix m_post; // the post-multiply matrix + + t_outlet *pivo, *pre, *post; + +} t_mtx_pivot; + +static void mtx_pivot_matrix(t_mtx_pivot *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + t_atom *m_pre, *m_post; + int i, j, k; + int min_rowcol = (row<col)?row:col; + t_matrixfloat *buffer, *buf; + int *i_pre, *i_post, *i_buf; + + int pivot_row, pivot_col; + + if (argc<2){ post("mtx_pivot: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_pivot: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + + adjustsize(&x->m, row, col); + adjustsize(&x->m_pre, row, row); + adjustsize(&x->m_post,col, col); + matrix_set(&x->m_pre, 0); + matrix_set(&x->m_post, 0); + + buffer = matrix2float(argv); + i_pre = (int *)getbytes(sizeof(int)*row); + i_post = (int *)getbytes(sizeof(int)*col); + + /* clear pre&post matrices */ + i=row; + i_buf=i_pre; + while(i--)*i_buf++=row-i-1; + i=col; + i_buf=i_post; + while(i--)*i_buf++=col-i-1; + + /* do the pivot thing */ + + for (k=0; k<min_rowcol-1; k++){ + // 1. find max_element + t_matrixfloat max = 0; + pivot_row = pivot_col = k; + + for(i=k; i<row; i++){ + buf=buffer+col*i+k; + + j=col-k; + while(j--){ + t_matrixfloat f = fabsf(*buf++); + if (f>max) { + max=f; + pivot_row = i; + pivot_col = col-j-1; + } + } + } + // 2. move max el to [k,k] + // 2a swap rows + if (k-pivot_row) { + t_matrixfloat *oldrow=buffer+col*k; + t_matrixfloat *newrow=buffer+col*pivot_row; + + i=col; + while(i--){ + t_matrixfloat f=*oldrow; + *oldrow++=*newrow; + *newrow++=f; + } + i=i_pre[k]; + i_pre[k]=i_pre[pivot_row]; + i_pre[pivot_row]=i; + } + // 2b swap columns + if (k-pivot_col) { + t_matrixfloat *oldcol=buffer+k; + t_matrixfloat *newcol=buffer+pivot_col; + + i=row; + while(i--){ + t_matrixfloat f=*oldcol; + *oldcol=*newcol; + *newcol=f; + oldcol+=col; + newcol+=col; + } + i=i_post[k]; + i_post[k]=i_post[pivot_col]; + i_post[pivot_col]=i; + } + } + + float2matrix(x->m.atombuffer, buffer); + + i=col; + m_post = x->m_post.atombuffer+2; + while(i--){ + SETFLOAT(m_post+i_post[i]*col+i, 1); + } + i=row; + m_pre = x->m_pre.atombuffer+2; + while(i--)SETFLOAT(m_pre+i_pre[i]+i*col, 1); + + + outlet_anything(x->post, gensym("matrix"), 2+col*col, x->m_post.atombuffer); + outlet_anything(x->pre, gensym("matrix"), 2+row*row, x->m_pre.atombuffer); + outlet_anything(x->pivo , gensym("matrix"), 2+row*col, x->m.atombuffer ); +} + +static void mtx_pivot_free(t_mtx_pivot *x) +{ + matrix_free(&x->m); + matrix_free(&x->m_pre); + matrix_free(&x->m_post); +} + +static void *mtx_pivot_new(void) +{ + t_mtx_pivot *x = (t_mtx_pivot *)pd_new(mtx_pivot_class); + + x->pivo = outlet_new(&x->x_obj, 0); + x->pre = outlet_new(&x->x_obj, 0); + x->post = outlet_new(&x->x_obj, 0); + + x->m.atombuffer = x->m_pre.atombuffer = x->m_post.atombuffer = 0; + x->m.row = x->m.col = x->m_pre.row = x->m_pre.col = x->m_post.row = x->m_post.col = 0; + + return(x); +} + +void mtx_pivot_setup(void) +{ + mtx_pivot_class = class_new(gensym("mtx_pivot"), (t_newmethod)mtx_pivot_new, (t_method)mtx_pivot_free, + sizeof(t_mtx_pivot), 0, 0, 0); + class_addmethod(mtx_pivot_class, (t_method)mtx_pivot_matrix, gensym("matrix"), A_GIMME, 0); + + class_sethelpsymbol(mtx_pivot_class, gensym("iemmatrix/mtx_transpose")); +} + +void iemtx_pivot_setup(void) +{ + mtx_pivot_setup(); +} diff --git a/src/mtx_print.c b/src/mtx_print.c new file mode 100644 index 0000000..3b1d028 --- /dev/null +++ b/src/mtx_print.c @@ -0,0 +1,60 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + + +#include "iemmatrix.h" + +/* mtx_print */ +static t_class *mtx_print_class; +static void mtx_print(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row; + if (argc<2){ + post("mtx_print : crippled matrix"); + return; + } + row = atom_getfloat(argv++); + col = atom_getfloat(argv++); + if(row*col>argc-2){ + post("mtx_print : sparse matrices not yet supported : use \"mtx_check\""); + return; + } + post("matrix:"); + while(row--){ + postatom(col, argv); + argv+=col; + endpost(); + } + endpost(); +} +static void *mtx_print_new(void) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_print_class); + x->row = x->col = 0; + x->atombuffer = 0; + return (x); +} +void mtx_print_setup(void) +{ + mtx_print_class = class_new(gensym("mtx_print"), (t_newmethod)mtx_print_new, + 0, sizeof(t_matrix), 0, 0, 0); + class_addmethod (mtx_print_class, (t_method)mtx_print, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_print_class, gensym("iemmatrix/matrix")); +} + +void iemtx_print_setup(void){ + mtx_print_setup(); +} + diff --git a/src/mtx_rand.c b/src/mtx_rand.c new file mode 100644 index 0000000..dee481a --- /dev/null +++ b/src/mtx_rand.c @@ -0,0 +1,93 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_rand */ +static t_class *mtx_rand_class; + +static void mtx_rand_seed(t_matrix *x, t_float f) +{ + x->current_row=f; +} +static int makeseed(void) +{ + static unsigned int random_nextseed = 1489853723; + random_nextseed = random_nextseed * 435898247 + 938284287; + return (random_nextseed & 0x7fffffff); +} +static void mtx_rand_random(t_matrix *x) +{ + long size = x->row * x->col; + t_atom *ap=x->atombuffer+2; + int val = x->current_row; + while(size--)SETFLOAT(ap+size, ((float)(((val=val*435898247+382842987)&0x7fffffff)-0x40000000))*(float)(0.5/0x40000000)+0.5); + x->current_row=val; +} + +static void mtx_rand_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row = atom_getfloat(argv++); + int col = atom_getfloat(argv++); + + if(!argv)return; + if(argc==1)col=row; + + adjustsize(x, row, col); + mtx_rand_random(x); + matrix_bang(x); +} +static void mtx_rand_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + matrix_matrix2(x, s, argc, argv); + mtx_rand_random(x); + matrix_bang(x); +} +static void mtx_rand_bang(t_matrix *x) +{ + mtx_rand_random(x); + matrix_bang(x); +} +static void *mtx_rand_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_rand_class); + int row, col; + outlet_new(&x->x_obj, 0); + x->col=x->row=0; + x->atombuffer=0; + x->current_row=makeseed(); + + if (argc) { + row=atom_getfloat(argv); + col=(argc>1)?atom_getfloat(argv+1):row; + adjustsize(x, row, col); + mtx_rand_random(x); + } + return (x); +} +void mtx_rand_setup(void) +{ + mtx_rand_class = class_new(gensym("mtx_rand"), (t_newmethod)mtx_rand_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addmethod(mtx_rand_class, (t_method)mtx_rand_matrix, gensym("matrix"), A_GIMME, 0); + class_addlist (mtx_rand_class, mtx_rand_list); + class_addbang (mtx_rand_class, mtx_rand_bang); + + class_addmethod(mtx_rand_class, (t_method)mtx_rand_seed, gensym("seed"), A_FLOAT, 0); + class_sethelpsymbol(mtx_rand_class, gensym("iemmatrix/mtx_rand")); +} + +void iemmtx_rand_setup(void){ + mtx_rand_setup(); +} + diff --git a/src/mtx_resize.c b/src/mtx_resize.c new file mode 100644 index 0000000..edc2e17 --- /dev/null +++ b/src/mtx_resize.c @@ -0,0 +1,103 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_resize */ + +static t_class *mtx_resize_class; +static void mtx_resize_list2(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int r, c; + if (argc<1)return; + if (argc>2)error("mtx_resize : only rows & cols are needed, skipping the rest"); + if (argc==1)r=c=atom_getfloat(argv++); + else{ + r=atom_getfloat(argv++); + c=atom_getfloat(argv++); + } + + if (r<0)r=0; + if (c<0)c=0; + + x->current_row = r; + x->current_col = c; +} + +static void mtx_resize_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv); + int col=atom_getfloat(argv+1); + int r = x->current_row, c = x->current_col; + int R=0, ROW, COL; + + if (argc<2){ post("mtx_add: crippled matrix"); return; } + if ((col<1)||(row<1)) { post("mtx_add: invalid dimensions"); return; } + if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; } + + if (!r)r=row; + if (!c)c=col; + + if (r==row && c==col) { // no need to change + outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv); + return; + } + + x->atombuffer=(t_atom *)getbytes((c*r+2)*sizeof(t_atom)); + setdimen(x, r, c); + matrix_set(x, 0); + + ROW=(r<row)?r:row; + COL=(c<col)?c:col; + R=ROW; + while(R--)memcpy(x->atombuffer+2+(ROW-R-1)*c, argv+2+(ROW-R-1)*col, COL*sizeof(t_atom)); + + matrix_bang(x); + + freebytes(x->atombuffer, (c*r+2)*sizeof(t_atom)); +} + +static void *mtx_resize_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_resize_class); + int c=0, r=0; + + if(argc){ + if(argc-1){ + r=atom_getfloat(argv); + c=atom_getfloat(argv+1); + } else r=c=atom_getfloat(argv); + if(c<0)c=0; + if(r<0)r=0; + } + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + outlet_new(&x->x_obj, 0); + x->current_row = r; + x->current_col = c; + x->row = x->col= 0; + x->atombuffer = 0; + + return (x); +} +void mtx_resize_setup(void) +{ + mtx_resize_class = class_new(gensym("mtx_resize"), (t_newmethod)mtx_resize_new, + 0, sizeof(t_matrix), 0, A_GIMME, 0); + class_addmethod (mtx_resize_class, (t_method)mtx_resize_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod (mtx_resize_class, (t_method)mtx_resize_list2, gensym(""), A_GIMME, 0); + class_sethelpsymbol(mtx_resize_class, gensym("iemmatrix/mtx_size")); +} +void iemtx_resize_setup(void){ + mtx_resize_setup(); +} + diff --git a/src/mtx_roll.c b/src/mtx_roll.c new file mode 100644 index 0000000..a437b06 --- /dev/null +++ b/src/mtx_roll.c @@ -0,0 +1,73 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_roll */ +/* roll the rows */ +static t_class *mtx_roll_class; + +static void mtx_roll_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + t_atom *ap; + int colroll = ((int)x->f%col+col)%col; + int c; + + if(row*col>argc-2) { + post("mtx_roll: sparse matrices not yet supported : use \"mtx_check\""); + return; + } + + adjustsize(x, row, col); + ap = x->atombuffer+2; + + c=col; + while(c--){ + t_atom *in = argv+col-c-1; + t_atom *out = ap +(col-c-1+colroll)%col; + int r = row; + while (r--){ + SETFLOAT(out, atom_getfloat(in)); + out+=col; + in+=col; + } + + } + + matrix_bang(x); +} + +static void *mtx_roll_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_roll_class); + floatinlet_new(&x->x_obj, &(x->f)); + outlet_new(&x->x_obj, 0); + + x->f=argc?atom_getfloat(argv):0; + x->col=x->row=0; + x->atombuffer=0; + return (x); +} +void mtx_roll_setup(void) +{ + mtx_roll_class = class_new(gensym("mtx_roll"), (t_newmethod)mtx_roll_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_roll_class, matrix_bang); + class_addmethod(mtx_roll_class, (t_method)mtx_roll_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_roll_class, gensym("iemmatrix/mtx_transpose")); +} +void iemtx_roll_setup(void){ + mtx_roll_setup(); +} diff --git a/src/mtx_row.c b/src/mtx_row.c new file mode 100644 index 0000000..e88aae8 --- /dev/null +++ b/src/mtx_row.c @@ -0,0 +1,120 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_row */ +static t_class *mtx_row_class; + +static void mtx_row_float(t_matrix *x, t_floatarg f) +{ + int i = f; + if(i<0)i=0; + x->current_row = i; +} +static void mtx_row_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + if (argc<2){ post("matrix : corrupt matrix passed"); return; } + row = atom_getfloat(argv); + col = atom_getfloat(argv+1); + if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; } + if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; } + matrix_matrix2(x, s, argc, argv); + matrix_bang(x); +} +static void mtx_row_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + if (argc==1){ + t_float f=atom_getfloat(argv); + t_atom *ap=x->atombuffer+2+(x->current_row-1)*x->col; + if (x->current_row>x->row){ + post("mtx_row : too high a row is to be set"); + return; + } + if (x->current_row){ + int n=x->col; + while(n--){ + SETFLOAT(ap, f); + ap++; + } + } + matrix_bang(x); + return; + } + + if (argc<x->col){ + post("mtx_row : row length is too small for %dx%d-matrix", x->row, x->col); + return; + } + if (x->current_row>x->row){ + post("mtx_row : too high a row is to be set"); + return; + } + if(x->current_row) {memcpy(x->atombuffer+2+(x->current_row-1)*x->col, argv, x->col*sizeof(t_atom)); + } else { + int r=x->row; + while(r--)memcpy(x->atombuffer+2+r*x->col, argv, x->col*sizeof(t_atom)); + } + matrix_bang(x); +} +static void *mtx_row_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_row_class); + int i, j, q; + + outlet_new(&x->x_obj, 0); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + x->current_row=0; + x->col=x->row=0; + x->atombuffer=0; + switch (argc) { + case 0:break; + case 1: + i = atom_getfloat(argv); + if (i<0)i=0; + if(i)adjustsize(x, i, i); + matrix_set(x, 0); + break; + case 2: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + break; + default: + i = atom_getfloat(argv++);if(i<0)i=0; + j = atom_getfloat(argv++);if(j<0)j=0; + q = atom_getfloat(argv++);if(q<0)q=0; + if(i*j)adjustsize(x, i, j); + matrix_set(x, 0); + x->current_row=q; + } + return (x); +} +void mtx_row_setup(void) +{ + mtx_row_class = class_new(gensym("mtx_row"), (t_newmethod)mtx_row_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_row_class, matrix_bang); + class_addlist (mtx_row_class, mtx_row_list); + class_addmethod(mtx_row_class, (t_method)mtx_row_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(mtx_row_class, (t_method)mtx_row_float, gensym(""), A_FLOAT, 0); + class_sethelpsymbol(mtx_row_class, gensym("iemmatrix/mtx_element")); +} + + +void iemmtx_row_setup(void) +{ + mtx_row_setup(); +} diff --git a/src/mtx_scroll.c b/src/mtx_scroll.c new file mode 100644 index 0000000..5b4fffa --- /dev/null +++ b/src/mtx_scroll.c @@ -0,0 +1,59 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_scroll */ +/* scroll the rows */ +static t_class *mtx_scroll_class; + +static void mtx_scroll_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + int rowscroll = ((int)x->f%row+row)%row; + + if(row*col>argc-2) { + post("mtx_scroll: sparse matrices not yet supported : use \"mtx_check\""); + return; + } + adjustsize(x, row, col); + + memcpy(x->atombuffer+2, argv+(row-rowscroll)*col, rowscroll*col*sizeof(t_atom)); + memcpy(x->atombuffer+2+rowscroll*col, argv, (row-rowscroll)*col*sizeof(t_atom)); + + matrix_bang(x); +} + +static void *mtx_scroll_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_scroll_class); + floatinlet_new(&x->x_obj, &(x->f)); + outlet_new(&x->x_obj, 0); + + x->f=argc?atom_getfloat(argv):0; + x->col=x->row=0; + x->atombuffer=0; + return (x); +} +void mtx_scroll_setup(void) +{ + mtx_scroll_class = class_new(gensym("mtx_scroll"), (t_newmethod)mtx_scroll_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_scroll_class, matrix_bang); + class_addmethod(mtx_scroll_class, (t_method)mtx_scroll_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_scroll_class, gensym("iemmatrix/mtx_transpose")); +} +void iemtx_scroll_setup(void){ + mtx_scroll_setup(); +} diff --git a/src/mtx_size.c b/src/mtx_size.c new file mode 100644 index 0000000..43dbba1 --- /dev/null +++ b/src/mtx_size.c @@ -0,0 +1,54 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_size */ +static t_class *mtx_size_class; +typedef struct _mtx_size +{ + t_object x_obj; + + int row; + int col; + + t_outlet *left, *right; +} t_mtx_size; + +static void mtx_size_matrix(t_mtx_size *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc<2)return; + outlet_float(x->right, atom_getfloat(argv+1)); + outlet_float(x->left, atom_getfloat(argv)); + +} + +static void *mtx_size_new(t_symbol *s, int argc, t_atom *argv) +{ + t_mtx_size *x = (t_mtx_size *)pd_new(mtx_size_class); + x->left = outlet_new(&x->x_obj, 0); + x->right = outlet_new(&x->x_obj, 0); + + return (x); +} +void mtx_size_setup(void) +{ + mtx_size_class = class_new(gensym("mtx_size"), (t_newmethod)mtx_size_new, + 0, sizeof(t_mtx_size), 0, A_GIMME, 0); + class_addmethod(mtx_size_class, (t_method)mtx_size_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_size_class, gensym("iemmatrix/mtx_size")); +} + +void iemtx_size_setup(void){ + mtx_size_setup(); +} diff --git a/src/mtx_tilde.c b/src/mtx_tilde.c new file mode 100644 index 0000000..88dc5f9 --- /dev/null +++ b/src/mtx_tilde.c @@ -0,0 +1,413 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + + +/* + the sigmatrix objects :: + mtx_*~ : multiply a n-vector of in~ with a matrix to get a m-vector of out~ + line~ between the 2 matrices, to make it useable as a mixer +*/ + + +/* --------------------------- matrix~ ---------------------------------- + * + * multiply a n-vector of signals with a (n*m) matrix, to get m output-streams. + * make the (n*m)-matrix of scalars to be liny~ + * + * 1703:forum::für::umläute:2001 + */ + +static t_class *mtx_multilde_class; + +typedef struct _mtx_multilde { + t_object x_obj; + + t_float time; + int ticksleft; + int retarget; + t_float msec2tick; + + t_float**value; + t_float**target; + t_float**increment; /* single precision is really a bad, especially when doing long line~s. + * but the biginc (like in msp's line~ (d_ctl.c) is far too expensive... */ + t_float**sigIN; + t_float**sigOUT; + t_float *sigBUF; + + int n_sigIN; /* columns */ + int n_sigOUT; /* rows */ + + int compatibility; /* 0=default; 1=zexy; 2=iemlib */ +} t_mtx_multilde; + +/* the message thing */ + +static void mtx_multilde_matrix_default(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row, c=0, r=0; + + if (argc<2){ + post("matrix~ : bad matrix !"); + return; + } + + row = atom_getfloat(argv++); + col = atom_getfloat(argv++); + argc-=2; + + if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ + post("matrix~ : matrix dimensions do not match !!"); + return; + } + if(argc<row*col){ + post("matrix~ : reduced matrices not yet supported"); + return; + } + + if (x->time<=0) { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); + x->time=x->ticksleft=x->retarget=0; + } else { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=atom_getfloat(argv++); + x->retarget=1; + } +} + +static void mtx_multilde_matrix_zexy(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row, c=0, r=0; + + if (argc<2){ + post("matrix~ : bad matrix !"); + return; + } + + row = atom_getfloat(argv++); + col = atom_getfloat(argv++); + argc-=2; + + if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ + post("matrix~ : matrix dimensions do not match !!"); + return; + } + if(argc<row*col){ + post("matrix~ : reduced matrices not yet supported"); + return; + } + + if (x->time<=0) { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); + x->time=x->ticksleft=x->retarget=0; + } else { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=atom_getfloat(argv++); + x->retarget=1; + } +} + +static void mtx_multilde_matrix_iemlib(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row, c=0, r=0; + + if (argc<2){ + post("matrix~ : bad matrix !"); + return; + } + + row = atom_getfloat(argv++); + col = atom_getfloat(argv++); + argc-=2; + + if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ + post("matrix~ : matrix dimensions do not match !!"); + return; + } + if(argc<row*col){ + post("matrix~ : reduced matrices not yet supported"); + return; + } + + if (x->time<=0) { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); + x->time=x->ticksleft=x->retarget=0; + } else { + for(r=0; r<row; r++) + for(c=0; c<col; c++) + x->target[c][r]=atom_getfloat(argv++); + x->retarget=1; + } +} +static void mtx_multilde_matrix(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv){ + switch (x->compatibility){ + default:mtx_multilde_matrix_default(x,s,argc,argv); + break; + case 1:mtx_multilde_matrix_zexy(x,s,argc,argv); + break; + case 2:mtx_multilde_matrix_iemlib(x,s,argc,argv); + break; + } +} + +static void mtx_multilde_stop(t_mtx_multilde *x) +{ + int c = x->n_sigOUT, r; + t_float *tgt, *val; + while(c--){ + tgt=x->target[c]; + val=x->value [c]; + r=x->n_sigIN; + while(r--)*tgt++=*val++; + } + x->ticksleft = x->retarget = 0; +} + + +/* the dsp thing */ + +static t_int *mtx_multilde_perform(t_int *w) +{ + t_mtx_multilde *x = (t_mtx_multilde *)(w[1]); + int n = (int)(w[2]); + + int r, c; + + t_float **out = x->sigOUT; + t_float **in = x->sigIN; + + t_float *buf = x->sigBUF, *sigBUF = buf; + + t_float **value = x->value; + t_float **target = x->target; + t_float **increment = x->increment; + + t_float *inc, *val, *tgt; + + int n_IN=x->n_sigIN, n_OUT=x->n_sigOUT; + + if (x->retarget) { + int nticks = x->time * x->msec2tick; + t_float oneovernos; + + if (!nticks) nticks = 1; + oneovernos = 1./(nticks*n); + x->ticksleft = nticks; + + c = n_OUT; + while(c--) { + inc=increment[c]; + val=value[c]; + tgt=target[c]; + r=n_IN; + while(r--)*inc++=(*tgt++-*val++)*oneovernos; + } + + x->retarget = 0; + } + + if (x->ticksleft) { + int N=n-1; + n=-1; + // while (n--) { + while(n++<N){ + c = n_OUT; + while(c--) { + t_float sum = 0; + val = value[c]+n_IN-1; + inc = increment[c]+n_IN-1; + r=n_IN; + + while(r--)sum+=in[r][n]*(*val--+=*inc--); + + sigBUF[c]=sum; + } + buf = sigBUF; + c = n_OUT; + while(c--)out[c][n]=*buf++; + } + if (!--x->ticksleft) { + c = n_OUT; + while(c--){ + val=value[c]; + tgt=target[c]; + r=n_IN; + while(r--)*val++=*tgt++; + } + } + } else { /* no ticks left */ + while (n--) { + c = n_OUT; + while(c--) { + t_float sum = 0; + val = value[c]+n_IN-1; + r = n_IN; + while(r--)sum+=in[r][n]**val--; + sigBUF[c]=sum; + } + buf = sigBUF; + c = n_OUT; + while(c--)out[c][n]=*buf++; + } + } + return (w+3); +} + +static void mtx_multilde_dsp(t_mtx_multilde *x, t_signal **sp) +{ + int o = x->n_sigOUT, i=x->n_sigIN, n=0; + t_float **dummy = x->sigIN; + + while(i--)*dummy++=sp[n++]->s_vec; + + dummy =x->sigOUT; + while(o--)dummy[o]=sp[n++]->s_vec; + + x->msec2tick = sp[0]->s_sr / (1000.f * sp[0]->s_n); + dsp_add(mtx_multilde_perform, 2, x, sp[0]->s_n); +} + + +/* setup/setdown things */ + +static void mtx_multilde_free(t_mtx_multilde *x) +{ + int i = x->n_sigOUT; + while(i--) { + freebytes(x->value [i], x->n_sigOUT * sizeof(t_float *)); + freebytes(x->target [i], x->n_sigOUT * sizeof(t_float *)); + freebytes(x->increment[i], x->n_sigOUT * sizeof(t_float *)); + } + + freebytes(x->value, sizeof(x->value)); + freebytes(x->target, sizeof(x->target)); + freebytes(x->increment, sizeof(x->increment)); + + freebytes(x->sigIN, x->n_sigIN * sizeof(t_float *)); + freebytes(x->sigOUT, x->n_sigOUT * sizeof(t_float *)); + freebytes(x->sigBUF, x->n_sigOUT * sizeof(t_float )); +} + +static void *mtx_multilde_new(t_symbol *s, int argc, t_atom *argv) +{ + t_mtx_multilde *x = (t_mtx_multilde *)pd_new(mtx_multilde_class); + int i; + int InOut=0; + x->compatibility=0; + + if(s==gensym("matrix~")){ // zexy-compat + error("[matrix~] is deprecated");//; use [mtx_*~] instead"); + x->compatibility=1; + InOut=1; + } + + if(s==gensym("matrix_mul~")){ // iemlib-compat + error("[matrix_mul~] is deprecated; use [mtx_*~] instead"); + x->compatibility=2; + InOut=1; + } + + x->time = 0; + + switch (argc) { + case 0: + x->n_sigIN = x->n_sigOUT = 1; + break; + case 1: + x->n_sigIN = x->n_sigOUT = atom_getfloat(argv); + break; + default: + x->time= atom_getfloat(argv+2); + case 2: + if(InOut){ + x->n_sigIN = atom_getfloat(argv); + x->n_sigOUT = atom_getfloat(argv+1); + } else { + x->n_sigOUT = atom_getfloat(argv); + x->n_sigIN = atom_getfloat(argv+1); + } + break; + } + + if (x->time<0) x->time=0; + if (x->n_sigIN <1) x->n_sigIN =1; + if (x->n_sigOUT<1) x->n_sigOUT=1; + + /* the inlets */ + i=x->n_sigIN-1; + while(i--)inlet_new(&x->x_obj,&x->x_obj.ob_pd,&s_signal,&s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + floatinlet_new(&x->x_obj, &x->time); + + /* the outlets */ + i=x->n_sigOUT; + while(i--)outlet_new(&x->x_obj,&s_signal); + + /* make all the buffers */ + x->sigIN = (t_float**)getbytes(x->n_sigIN * sizeof(t_float*)); + x->sigOUT = (t_float**)getbytes(x->n_sigOUT * sizeof(t_float*)); + x->sigBUF = (t_float *)getbytes(x->n_sigOUT * sizeof(t_float )); + + x->value = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); + x->target = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); + x->increment = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); + + i = x->n_sigOUT; + while(i--){ + int j = x->n_sigIN; + x->sigOUT [i] = 0; + x->value [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); + x->target [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); + x->increment[i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); + + while(j--)x->value[i][j]=x->target[i][j]=x->increment[i][j]=0; + } + + i = x->n_sigIN; + while(i--)x->sigIN[i] = 0; + + x->msec2tick = x->ticksleft = x->retarget = 0; + return (x); +} + +static void mtx_multilde_setup(void) +{ + mtx_multilde_class = class_new(gensym("mtx_*~"), (t_newmethod)mtx_multilde_new, + (t_method)mtx_multilde_free, + sizeof(t_mtx_multilde), 0, A_GIMME, 0); + + class_addcreator((t_newmethod)mtx_multilde_new, gensym("matrix~"), A_GIMME,0); + + class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_dsp, gensym("dsp"), 0); + class_addmethod(mtx_multilde_class, nullfn, gensym("signal"), 0); + + class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_matrix, gensym(""), A_GIMME, 0); + class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_stop, gensym("stop"), 0); + + class_sethelpsymbol(mtx_multilde_class, gensym("iemmatrix/matrix~")); +} + +void mtx_tilde_setup(void) +{ + mtx_multilde_setup(); +} diff --git a/src/mtx_trace.c b/src/mtx_trace.c new file mode 100644 index 0000000..ba5b3db --- /dev/null +++ b/src/mtx_trace.c @@ -0,0 +1,57 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_trace */ +static t_class *mtx_trace_class; +typedef struct _mtx_trace +{ + t_object x_obj; + t_float trace; +} t_mtx_trace; +static void mtx_trace_bang(t_mtx_trace *x) +{ + outlet_float(x->x_obj.ob_outlet, x->trace); +} +static void mtx_trace_matrix(t_mtx_trace *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + int length=(col<row)?col:row; + t_float trace = 0; + if(row*col>argc-2)post("mtx_trace: sparse matrices not yet supported : use \"mtx_check\""); + else while(length--)trace+=atom_getfloat(argv+length*(col+1)); + x->trace=trace; + mtx_trace_bang(x); +} +static void *mtx_trace_new(t_symbol *s, int argc, t_atom *argv) +{ + t_mtx_trace *x = (t_mtx_trace *)pd_new(mtx_trace_class); + outlet_new(&x->x_obj, 0); + x->trace=0; + return (x); +} +void mtx_trace_setup(void) +{ + mtx_trace_class = class_new(gensym("mtx_trace"), (t_newmethod)mtx_trace_new, + 0, sizeof(t_mtx_trace), 0, A_GIMME, 0); + class_addbang (mtx_trace_class, mtx_trace_bang); + class_addmethod(mtx_trace_class, (t_method)mtx_trace_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_trace_class, gensym("iemmatrix/mtx_trace")); +} + +void iemtx_trace_setup(void) +{ + mtx_trace_setup(); +} diff --git a/src/mtx_transpose.c b/src/mtx_transpose.c new file mode 100644 index 0000000..7034cae --- /dev/null +++ b/src/mtx_transpose.c @@ -0,0 +1,67 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_transpose */ +static t_class *mtx_transpose_class; + +static void mtx_transpose_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv) +{ + int row=atom_getfloat(argv++); + int col=atom_getfloat(argv++); + t_atom *ap; + int r, c; + + if(row*col>argc-2) { + post("mtx_transpose: sparse matrices not yet supported : use \"mtx_check\""); + return; + } + if (col*row!=x->col*x->row) { + freebytes(x->atombuffer, (x->col*x->row+2)*sizeof(t_atom)); + x->atombuffer = (t_atom *)getbytes((row*col+2)*sizeof(t_atom)); + } + ap = x->atombuffer+2; + setdimen(x, col, row); + r = row; + while(r--){ + c=col; + while(c--) { + t_float f = atom_getfloat(argv+r*col+c); + SETFLOAT(ap+c*row+r, f); + } + } + + matrix_bang(x); +} + +static void *mtx_transpose_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_transpose_class); + outlet_new(&x->x_obj, 0); + x->col=x->row=0; + x->atombuffer=0; + return (x); +} +void mtx_transpose_setup(void) +{ + mtx_transpose_class = class_new(gensym("mtx_transpose"), (t_newmethod)mtx_transpose_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addbang (mtx_transpose_class, matrix_bang); + class_addmethod(mtx_transpose_class, (t_method)mtx_transpose_matrix, gensym("matrix"), A_GIMME, 0); + class_sethelpsymbol(mtx_transpose_class, gensym("iemmatrix/mtx_transpose")); +} + +void iemtx_transpose_setup(void){ + mtx_transpose_setup(); +} diff --git a/src/mtx_zeros.c b/src/mtx_zeros.c new file mode 100644 index 0000000..a340967 --- /dev/null +++ b/src/mtx_zeros.c @@ -0,0 +1,56 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * (c) IOhannes m zmölnig, forum::für::umläute + * + * IEM, Graz + * + * this code is published under the LGPL + * + */ +#include "iemmatrix.h" + +/* mtx_zeros */ +static t_class *mtx_zeros_class; +static void *mtx_zeros_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix *x = (t_matrix *)pd_new(mtx_zeros_class); + int col=0, row=0; + outlet_new(&x->x_obj, 0); + x->row = x->col = 0; + x->atombuffer = 0; + switch(argc) { + case 0: + break; + case 1: + col=row=atom_getfloat(argv); + break; + default: + row=atom_getfloat(argv++); + col=atom_getfloat(argv); + } + if(col<0)col=0; + if(row<0)row=0; + if (col*row){ + x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom)); + setdimen(x, row, col); + matrix_set(x, 0); + } + return (x); +} +void mtx_zeros_setup(void) +{ + mtx_zeros_class = class_new(gensym("mtx_zeros"), (t_newmethod)mtx_zeros_new, + (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0); + class_addlist(mtx_zeros_class, matrix_zeros); + class_addbang(mtx_zeros_class, matrix_bang); + class_addmethod(mtx_zeros_class, (t_method)matrix_zeros, gensym("matrix"), A_GIMME, 0); + + class_sethelpsymbol(mtx_zeros_class, gensym("iemmatrix/mtx_special")); +} +void iemmtx_zeros_setup(void){ + mtx_zeros_setup(); +} |