aboutsummaryrefslogtreecommitdiff
path: root/src/mtx_slice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mtx_slice.c')
-rw-r--r--src/mtx_slice.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/mtx_slice.c b/src/mtx_slice.c
new file mode 100644
index 0000000..7dc1042
--- /dev/null
+++ b/src/mtx_slice.c
@@ -0,0 +1,215 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * Copyright (c) 2005, Franz Zotter
+ * IEM, Graz, Austria
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ */
+
+#include "iemmatrix.h"
+
+static t_class *mtx_slice_class;
+
+typedef struct _MTXslice_ MTXslice;
+struct _MTXslice_
+{
+ t_object x_obj;
+ int slice_size;
+ int slice_startcol;
+ int slice_startrow;
+ int slice_stopcol;
+ int slice_stoprow;
+
+ t_outlet *list_outlet;
+
+ t_atom *list_out;
+};
+
+static void deleteMTXSlice (MTXslice *mtx_slice_obj)
+{
+ if (mtx_slice_obj->list_out)
+ freebytes (mtx_slice_obj->list_out, sizeof(t_atom)*(mtx_slice_obj->slice_size+2));
+}
+
+static void mTXSliceIndexList (MTXslice *mtx_slice_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ int startcol;
+ int startrow;
+ int stopcol;
+ int stoprow;
+ t_symbol *endsym = gensym("end");
+ t_atom *list_out = mtx_slice_obj->list_out;
+
+ if (argc<4) {
+ post("mtx_slice: invalid index vector: <startrow><startcol><stoprow><stopcol>");
+ return;
+ }
+ startrow = atom_getint(&argv[0]);
+ startcol = atom_getint(&argv[1]);
+ stoprow = atom_getint(&argv[2]);
+ stopcol = atom_getint(&argv[3]);
+ if (atom_getsymbol(&argv[0])==endsym) {
+ startrow = -1;
+ }
+ if (atom_getsymbol(&argv[1])==endsym) {
+ startcol = -1;
+ }
+ if (atom_getsymbol(&argv[2])==endsym) {
+ stoprow = -1;
+ }
+ if (atom_getsymbol(&argv[3])==endsym) {
+ stopcol = -1;
+ }
+
+ if (((startrow<1) && (atom_getsymbol(&argv[0])!=endsym)) ||
+ ((startcol<1) && (atom_getsymbol(&argv[1])!=endsym))) {
+ post("mtx_slice: row and column indices must be >0, or misused \"end\" keyword");
+ return;
+ }
+
+ if (((startrow>stoprow) && (atom_getsymbol(&argv[2])!=endsym)) ||
+ ((startcol>stopcol) && (atom_getsymbol (&argv[3])!=endsym))) {
+ post("mtx_slice: start_index<stop_index for rows and columns, or misused \"end\" keyword");
+ return;
+ }
+
+ mtx_slice_obj->slice_startrow = startrow;
+ mtx_slice_obj->slice_startcol = startcol;
+ mtx_slice_obj->slice_stoprow = stoprow;
+ mtx_slice_obj->slice_stopcol = stopcol;
+}
+
+static void *newMTXSlice (t_symbol *s, int argc, t_atom *argv)
+{
+ MTXslice *mtx_slice_obj = (MTXslice *) pd_new (mtx_slice_class);
+ if (argc==4)
+ mTXSliceIndexList (mtx_slice_obj, gensym("list"),argc,argv);
+ else {
+ mtx_slice_obj->slice_startrow = 1;
+ mtx_slice_obj->slice_startcol = 1;
+ mtx_slice_obj->slice_stopcol = -1;
+ mtx_slice_obj->slice_stoprow = -1;
+ }
+ mtx_slice_obj->list_outlet = outlet_new (&mtx_slice_obj->x_obj, gensym("matrix"));
+ inlet_new(&mtx_slice_obj->x_obj, &mtx_slice_obj->x_obj.ob_pd, gensym("list"),gensym(""));
+ return ((void *) mtx_slice_obj);
+}
+
+static void mTXSliceBang (MTXslice *mtx_slice_obj)
+{
+ if (mtx_slice_obj->list_out)
+ outlet_anything(mtx_slice_obj->list_outlet, gensym("matrix"),
+ mtx_slice_obj->slice_size+2, mtx_slice_obj->list_out);
+}
+/*
+ static void copyList (int size, t_atom *x, t_atom *y)
+ {
+ while(size--)
+ *y++=*x++;
+ }
+*/
+
+static void writeVectorIntoList (int n, t_atom *x, t_atom *y)
+{
+ for (;n--;x++,y++)
+ *y = *x;
+}
+
+static void writeSliceIntoList (int slicerows, const int slicecols, int columns, t_atom *x, t_atom *y)
+{
+ for (;slicerows--;x+=columns,y+=slicecols)
+ writeVectorIntoList(slicecols, x, y);
+}
+
+static void mTXSliceMatrix (MTXslice *mtx_slice_obj, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ int rows = atom_getint (argv++);
+ int columns = atom_getint (argv++);
+ int size = rows * columns;
+ int list_size = argc - 2;
+ t_atom *list_in = argv;
+ t_atom *list_out = mtx_slice_obj->list_out;
+ int stopcol = mtx_slice_obj->slice_stopcol;
+ int stoprow = mtx_slice_obj->slice_stoprow;
+ int startrow = mtx_slice_obj->slice_startrow;
+ int startcol = mtx_slice_obj->slice_startcol;
+ int slicecols, slicerows, slicesize;
+
+ // size check
+ if (!size) {
+ post("mtx_slice: invalid dimensions");
+ return;
+ }
+ else if (list_size<size) {
+ post("mtx_slice: sparse matrix not yet supported: use \"mtx_check\"");
+ return;
+ }
+ startrow = (startrow==-1)?rows:startrow;
+ startcol = (startcol==-1)?columns:startcol;
+ stoprow = (stoprow==-1)?rows:stoprow;
+ stopcol = (stopcol==-1)?columns:stopcol;
+ if ((!startrow)||(!startcol)) {
+ post("mtx_slice: indices must be >0");
+ return;
+ }
+ if ((stopcol > columns) ||
+ (stoprow > rows)) {
+ post("mtx_slice: slice index exceeds matrix dimensions");
+ return;
+ }
+ if ((stoprow<startrow) || (stopcol<startcol)) {
+ post("mtx_slice: start_index<stop_index for rows and columns, or misused \"end\" keyword");
+ return;
+ }
+ slicerows = stoprow-startrow+1;
+ slicecols = stopcol-startcol+1;
+ slicesize = slicerows*slicecols;
+
+ // main part
+ if (slicesize != mtx_slice_obj->slice_size) {
+ if (!list_out)
+ list_out = (t_atom *) getbytes (sizeof (t_atom) * (slicesize + 2));
+ else
+ list_out = (t_atom *) resizebytes (list_out,
+ sizeof (t_atom) * (mtx_slice_obj->slice_size+2),
+ sizeof (t_atom) * (slicesize + 2));
+ mtx_slice_obj->slice_size = slicesize;
+ mtx_slice_obj->list_out = list_out;
+ }
+ list_out += 2;
+ list_in += columns * (startrow-1) + startcol-1;
+ writeSliceIntoList (slicerows, slicecols,
+ columns, list_in,list_out);
+ list_out = mtx_slice_obj->list_out;
+ SETSYMBOL(list_out, gensym("matrix"));
+ SETFLOAT(list_out, slicerows);
+ SETFLOAT(&list_out[1], slicecols);
+ outlet_anything(mtx_slice_obj->list_outlet, gensym("matrix"),
+ slicesize+2, list_out);
+}
+
+void mtx_slice_setup (void)
+{
+ mtx_slice_class = class_new
+ (gensym("mtx_slice"),
+ (t_newmethod) newMTXSlice,
+ (t_method) deleteMTXSlice,
+ sizeof (MTXslice),
+ CLASS_DEFAULT, A_GIMME, 0);
+ class_addbang (mtx_slice_class, (t_method) mTXSliceBang);
+ class_addmethod (mtx_slice_class, (t_method) mTXSliceMatrix, gensym("matrix"), A_GIMME,0);
+ class_addmethod (mtx_slice_class, (t_method) mTXSliceIndexList, gensym(""), A_GIMME,0);
+ class_sethelpsymbol (mtx_slice_class, gensym("iemmatrix/mtx_slice"));
+}
+
+void iemtx_slice_setup(void){
+ mtx_slice_setup();
+}