aboutsummaryrefslogtreecommitdiff
path: root/tabfind/tabfind.c
diff options
context:
space:
mode:
Diffstat (limited to 'tabfind/tabfind.c')
-rw-r--r--tabfind/tabfind.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/tabfind/tabfind.c b/tabfind/tabfind.c
new file mode 100644
index 0000000..e1c2d2a
--- /dev/null
+++ b/tabfind/tabfind.c
@@ -0,0 +1,148 @@
+/* ---------- tabfind: return the index of the input (float or list of floats)in the given table */
+/* based on tabread in d_array.c */
+/* Started 20081120 by Martin Peach (mrpeach) */
+
+#include "m_pd.h"
+
+/* #define USE_GETFLOATWORDS *//* if garray_getfloatwords is implemented */
+/* garray_getfloatwords uses t_word but doesn't exist in some versions of pd */
+/* garray_getfloatarray uses t_float but is not 64-bit */
+
+static t_class *tabfind_class;
+
+typedef struct _tabfind
+{
+ t_object x_obj;
+ t_symbol *x_arrayname;
+ t_int x_nth; /* which match to find */
+} t_tabfind;
+
+static void tabfind_float(t_tabfind *x, t_float f);
+static void tabfind_list(t_tabfind *x, t_symbol *s, int argc, t_atom *argv);
+static void tabfind_nth(t_tabfind *x, t_float nth);
+static void tabfind_set(t_tabfind *x, t_symbol *s);
+static void *tabfind_new(t_symbol *s);
+void tabfind_setup(void);
+
+static void tabfind_nth(t_tabfind *x, t_float fnth)
+{
+/* set to find the nth instance of the key */
+ int inth;
+ if (fnth >= 1) inth = (int)fnth;
+ else
+ {
+ inth = 1;
+ pd_error(x, "tabfind: nth must be at least 1");
+ }
+ x->x_nth = inth;
+}
+
+static void tabfind_list(t_tabfind *x, t_symbol *s, int argc, t_atom *argv)
+{
+ /* find the nth occurrence of the list of floats argv in the array */
+ t_garray *a;
+ int npoints;
+#ifdef USE_GETFLOATWORDS
+ t_word *vec;
+#else
+ t_float *vec;
+#endif
+ int n, count = 0;
+ int i, j;
+
+ /* first check the list for floatness... */
+ for (i = 0; i < argc; ++i)
+ {
+ if (argv[i].a_type != A_FLOAT)
+ {
+ pd_error(x, "tabfind: list must be all floats");
+ return;
+ }
+ }
+
+ /* then find the array again... */
+ if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
+ pd_error(x, "tabfind: %s: no such array", x->x_arrayname->s_name);
+#ifdef USE_GETFLOATWORDS
+ else if (!garray_getfloatwords(a, &npoints, &vec))
+#else
+ else if (!garray_getfloatarray(a, &npoints, &vec))
+#endif
+ pd_error(x, "tabfind: %s: bad template for tabread", x->x_arrayname->s_name);
+ else
+ /* try to find the nth instance of the list in a and output its index */
+ {
+ for (n = 0; n < npoints; ++n)
+ {
+ for (i = 0; ((i < argc) && ((n+i) < npoints)); ++i)
+#ifdef USE_GETFLOATWORDS
+ if (vec[n+i].w_float != argv[i].a_w.w_float) break;
+#else
+ if (vec[n+i] != argv[i].a_w.w_float) break;
+#endif
+ if ((i == argc) && (x->x_nth == ++count)) break;
+ }
+ outlet_float(x->x_obj.ob_outlet, n);
+ }
+}
+
+static void tabfind_float(t_tabfind *x, t_float f)
+{
+ /* find the nth occurrence of the float f in the array */
+ t_garray *a;
+ int npoints;
+#ifdef USE_GETFLOATWORDS
+ t_word *vec;
+#else
+ t_float *vec;
+#endif
+ int n, count = 0;
+
+ if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
+ pd_error(x, "tabfind: %s: no such array", x->x_arrayname->s_name);
+#ifdef USE_GETFLOATWORDS
+ else if (!garray_getfloatwords(a, &npoints, &vec))
+#else
+ else if (!garray_getfloatarray(a, &npoints, &vec))
+#endif
+ pd_error(x, "tabfind: %s: bad template for tabread", x->x_arrayname->s_name);
+ else
+ /* find the nth instance of f in a and output its index */
+ {
+ for (n = 0; n < npoints; ++n)
+ {
+#ifdef USE_GETFLOATWORDS
+ if (vec[n].w_float == f)
+#else
+ if (vec[n] == f)
+#endif
+ if (x->x_nth == ++count) break;
+ }
+ outlet_float(x->x_obj.ob_outlet, n);
+ }
+}
+
+static void tabfind_set(t_tabfind *x, t_symbol *s)
+{
+ /* set the name of the array we're working on */
+ x->x_arrayname = s;
+}
+
+static void *tabfind_new(t_symbol *s)
+{
+ t_tabfind *x = (t_tabfind *)pd_new(tabfind_class);
+ x->x_arrayname = s;
+ outlet_new(&x->x_obj, &s_float);
+ x->x_nth = 1;
+ return (x);
+}
+
+void tabfind_setup(void)
+{
+ tabfind_class = class_new(gensym("tabfind"), (t_newmethod)tabfind_new,
+ 0, sizeof(t_tabfind), 0, A_DEFSYM, 0);
+ class_addfloat(tabfind_class, (t_method)tabfind_float);
+ class_addlist(tabfind_class, (t_method)tabfind_list);
+ class_addmethod(tabfind_class, (t_method)tabfind_nth, gensym("nth"), A_FLOAT, 0);
+ class_addmethod(tabfind_class, (t_method)tabfind_set, gensym("set"), A_SYMBOL, 0);
+}