From b02eaa7f9a317b1ca5ac91276b1e7ce7ca48a32b Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Fri, 21 Nov 2008 21:25:21 +0000 Subject: An external to find a float or sequence of floats in a table/array. svn path=/trunk/externals/mrpeach/; revision=10374 --- tabfind/tabfind-help.pd | 43 ++++++++++++++ tabfind/tabfind.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 tabfind/tabfind-help.pd create mode 100644 tabfind/tabfind.c diff --git a/tabfind/tabfind-help.pd b/tabfind/tabfind-help.pd new file mode 100644 index 0000000..68b0bdc --- /dev/null +++ b/tabfind/tabfind-help.pd @@ -0,0 +1,43 @@ +#N canvas 580 58 510 358 10; +#X obj 0 289 table pig; +#X obj 94 128 tabfind pig; +#X obj -3 14 f; +#X obj -3 -3 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -257985 +-1; +#X msg 89 106 set wig; +#X obj 64 289 table wig; +#X msg 70 87 set pig; +#X msg 0 256 \; wig 0 88 89 88 83 22 0 11; +#X msg 51 68 nth \$1; +#X text 107 51 By default tabfind finds the first instance of the input. +; +#X text 98 67 The [nth( message sets which instance to fnd.; +#X obj 55 184 loadbang; +#X text 131 86 The [set( message sets which array to look in.; +#X text 148 149 index \, or length of array if input not found.; +#X msg 16 33 76 72 71; +#X msg 45 211 \; pig 0 72 73 75 76 72 71 72 76 88 0 0 99 100 101 102 +76 72 71 99 98 97; +#X text 281 287 2008_11_20 Martin Peach; +#X obj 51 52 nbx 5 14 1 1e+037 0 1 empty empty empty 0 -8 0 10 -4034 +-16662 -1 1 256; +#X obj 12 -3 nbx 3 14 -1e+037 1e+037 0 1 empty empty empty 0 -8 0 10 +-4034 -16662 -1 99 256; +#X obj 94 150 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -8 0 +10 -4032 -258113 -1 15 256; +#X text -4 -30 [tabfind] searches an array and outputs the index at +which the input float or list of floats is found.; +#X text 166 127 argument is the name of the array to search in.; +#X text 50 -4 <--find this number.; +#X text 71 33 <-- or find this sequence.; +#X connect 1 0 19 0; +#X connect 2 0 1 0; +#X connect 3 0 2 0; +#X connect 4 0 1 0; +#X connect 6 0 1 0; +#X connect 8 0 1 0; +#X connect 11 0 15 0; +#X connect 11 0 7 0; +#X connect 14 0 1 0; +#X connect 17 0 8 0; +#X connect 18 0 2 1; 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); +} -- cgit v1.2.1