/* sieve takes a map like 0 1 3 4 7 and only returns the number if it is present * in the map, or returns the closest, or the next up or down (wrapped) * Copyright (c) 2007, Dr Edward Kelly * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * * provided with the distribution. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "m_pd.h" #include #include #define MAXENTRIES 2048 #define LASTENTRY 2047 static t_class *sieve_class; /* mode = 0 : block when absent, 1: nearest when absent, 2: shunt when absent */ typedef struct _map { t_atom map[MAXENTRIES]; t_atom nomap[MAXENTRIES]; } t_map; typedef struct _sieve { t_object x_obj; t_map x_map; t_float input, mode, max, outmap; t_outlet *mapped, *value, *mapout, *inst; } t_sieve; void sieve_float(t_sieve *x, t_floatarg fin) { int i, ip, in, arg, arga, argb, argaout, argbout, argxa, argxb, itest, itesta, itestb, iresult; itest = itesta = itestb = iresult = arga = argb = arg = 0; float test, testa, testb, fresult; test = testa = testb = fresult = 0; x->input = arg = fin; if (x->mode == 0) /* only let through floats when the corresponding index contains != 0 */ { test = fin < 0 ? 0 : atom_getfloatarg(arg, MAXENTRIES, x->x_map.map); if(test!=0) { outlet_bang(x->inst); outlet_float(x->value, test); outlet_float(x->mapped, arg); } } else if (x->mode == 1) /* find the nearest float whose (int) index is != 0 */ { test = fin < 0 ? 0 : atom_getfloatarg(arg, MAXENTRIES, x->x_map.map); if(test!=0) { outlet_bang(x->inst); outlet_float(x->value, test); outlet_float(x->mapped, arg); } else { arga = argb = arg; while(itest == 0 && (arga > -1 || argb < MAXENTRIES)) { arga--; argb++; argxa = arga >= 0 ? arga : 0; argxb = argb <= LASTENTRY ? argb : LASTENTRY; testa = atom_getfloatarg(argxa, MAXENTRIES, x->x_map.map); testb = atom_getfloatarg(argxb, MAXENTRIES, x->x_map.map); itesta = testa != 0 ? 1 : 0; itestb = testb != 0 ? 1 : 0; itest = fin < 0 ? 0 : itesta + itestb; } switch(itest) { case 2: /* if we find two at equal distance, output the higher */ if (x->mode == 1) { outlet_float(x->value, testb); outlet_float(x->mapped, argb); } else { outlet_float(x->value, testa); outlet_float(x->mapped, arga); } case 1: iresult = itesta == 1 ? arga : argb; fresult = itesta == 1 ? testa : testb; outlet_float(x->value, fresult); outlet_float(x->mapped, iresult); case 0: break; } } } else if (x->mode==2) /* if the index is 0, find the next highest */ { itest = 0; test = fin < 0 ? 0 : atom_getfloatarg(arg, MAXENTRIES, x->x_map.map); if(test!=0) { outlet_bang(x->inst); outlet_float(x->value, test); outlet_float(x->mapped, arg); } else { arga = arg; while(itest == 0 && (x->max > 0)) { arga = (arga + 1) <= LASTENTRY ? (arga + 1) : 0; testa = atom_getfloatarg(arga, MAXENTRIES, x->x_map.map); itest = testa != 0 ? 1 : 0; } if(x->max > 0 && fin >= 0) { outlet_float(x->value, testa); outlet_float(x->mapped, arga); } } } else if (x->mode == 3) /* if the index is 0, find the next lowest */ { itest = 0; test = fin < 0 ? 0 : atom_getfloatarg(arg, MAXENTRIES, x->x_map.map); if(test!=0) { outlet_bang(x->inst); outlet_float(x->value, test); outlet_float(x->mapped, arg); } else { arga = arg; while(itest == 0 && (x->max > 0)) { argb = arga - 1; arga = argb >= 0 ? argb : LASTENTRY; testa = atom_getfloatarg(arga, MAXENTRIES, x->x_map.map); itest = testa != 0 ? 1 : 0; } } outlet_float(x->value, testa); outlet_float(x->mapped, arga); } } void sieve_set(t_sieve *x, t_floatarg fmap, t_floatarg fval) /* set one value in the array */ { float fvaller; if(fmap < MAXENTRIES && fmap >= 0) { int imap = (int)fmap; fvaller = fval != 0 ? 0 : 1; SETFLOAT(&x->x_map.map[imap], fval); SETFLOAT(&x->x_map.nomap[imap], fvaller); x->max = fmap > x->max ? fmap : x->max; } } void sieve_delete(t_sieve *x, t_floatarg loc) /* remove a value */ { int addloc = (int)loc + 1; int maxentry = (int)x->max; int i; float buffer; if(locmax && loc>=0) { for(i=addloc;i<=maxentry;i++) { buffer = atom_getfloatarg(i,MAXENTRIES,x->x_map.map); SETFLOAT(&x->x_map.map[i-1],buffer); if(buffer!=0) { SETFLOAT(&x->x_map.nomap[i-1],0); } else { SETFLOAT(&x->x_map.nomap[i-1],1); } } SETFLOAT(&x->x_map.map[maxentry],0); x->max--; } else if(loc==x->max) { x->max--; SETFLOAT(&x->x_map.map[maxentry],0); } } void sieve_shunt(t_sieve *x, t_floatarg loc) /* move down and decrement subsequent */ { int addloc = (int)loc + 1; int maxentry = (int)x->max; int i; float buffer, shunt; if(locmax && loc>=0) { for(i=addloc;i<=maxentry;i++) { buffer = atom_getfloatarg(i,MAXENTRIES,x->x_map.map); shunt = buffer - 1; SETFLOAT(&x->x_map.map[i-1],shunt); if(shunt!=0) { SETFLOAT(&x->x_map.nomap[i-1],0); } else { SETFLOAT(&x->x_map.nomap[i-1],1); } } SETFLOAT(&x->x_map.map[maxentry],0); x->max--; } else if(loc==x->max) { x->max--; SETFLOAT(&x->x_map.map[maxentry],0); } } void sieve_shift(t_sieve *x, t_floatarg loc) /* move up and increment subsequent */ { int location = (int)loc; int addloc; int maxentry = (int)x->max+1; int i; float buffer, shift; if(location>=0 && maxentry < MAXENTRIES) { for(i=maxentry;i>=location;i--) { buffer = atom_getfloatarg(i-1,MAXENTRIES,x->x_map.map); shift = buffer + 1; SETFLOAT(&x->x_map.map[i],shift); if(shift!=0) { SETFLOAT(&x->x_map.nomap[i],0); } else { SETFLOAT(&x->x_map.nomap[i],1); } } x->max++; } } void sieve_insert(t_sieve *x, t_floatarg loc, t_floatarg val) /* insert a value at specific location, moving subsequent values up */ { int location = (int)loc; int maxentry = (int)x->max+1; int i; float buffer; if(loc>=0 && maxentry < MAXENTRIES) { for(i=maxentry;i>=location;i--) { buffer = atom_getfloatarg(i-1,MAXENTRIES,x->x_map.map); SETFLOAT(&x->x_map.map[i],buffer); if(buffer!=0) { SETFLOAT(&x->x_map.nomap[i],0); } else { SETFLOAT(&x->x_map.nomap[i],1); } } x->max++; SETFLOAT(&x->x_map.map[location], val); if(val) { SETFLOAT(&x->x_map.nomap[location],0); } else { SETFLOAT(&x->x_map.nomap[location],1); } } } void sieve_get(t_sieve *x, t_floatarg inv) /* outlet to map or inverse */ { if(inv!=0) { outlet_list(x->mapout, gensym("list"), x->max+1, x->x_map.nomap); } else outlet_list(x->mapout, gensym("list"), x->max+1, x->x_map.map); x->outmap = inv; } void sieve_clear(t_sieve *x) { int i; for(i=0;ix_map.map[i], 0); SETFLOAT(&x->x_map.nomap[i], 1); } x->max = 0; } void sieve_map(t_sieve *x, t_symbol *s, int argc, t_atom *argv) /* set the whole map */ { int i; for(i=0;ix_map.map+i, 0); SETFLOAT(x->x_map.nomap+i, 1); } x->max = 0; float arg; for(i=0;ix_map.map[i], arg); SETFLOAT(&x->x_map.nomap[i], 0); x->max = i; } } if (x->max > 0 && x->outmap == 0) { outlet_list(x->mapout, gensym("list"), x->max+1, x->x_map.map); } else if (x->max > 0 && x->outmap == 1) { outlet_list(x->mapout, gensym("list"), x->max+1, x->x_map.nomap); } } void sieve_mode(t_sieve *x, t_floatarg fmode) { x->mode = fmode < 0 ? 0 : fmode > 3 ? 3 : fmode; } void sieve_debug(t_sieve *x) { float ele0, ele1, ele2, ele3, ele4, ele5, ele6, ele7, ele8, ele9; float nle0, nle1, nle2, nle3, nle4, nle5, nle6, nle7, nle8, nle9; ele0 = atom_getfloatarg(0, MAXENTRIES, x->x_map.map); ele1 = atom_getfloatarg(1, MAXENTRIES, x->x_map.map); ele2 = atom_getfloatarg(2, MAXENTRIES, x->x_map.map); ele3 = atom_getfloatarg(3, MAXENTRIES, x->x_map.map); ele4 = atom_getfloatarg(4, MAXENTRIES, x->x_map.map); ele5 = atom_getfloatarg(5, MAXENTRIES, x->x_map.map); ele6 = atom_getfloatarg(6, MAXENTRIES, x->x_map.map); ele7 = atom_getfloatarg(7, MAXENTRIES, x->x_map.map); ele8 = atom_getfloatarg(8, MAXENTRIES, x->x_map.map); ele9 = atom_getfloatarg(9, MAXENTRIES, x->x_map.map); nle0 = atom_getfloatarg(0, MAXENTRIES, x->x_map.nomap); nle1 = atom_getfloatarg(1, MAXENTRIES, x->x_map.nomap); nle2 = atom_getfloatarg(2, MAXENTRIES, x->x_map.nomap); nle3 = atom_getfloatarg(3, MAXENTRIES, x->x_map.nomap); nle4 = atom_getfloatarg(4, MAXENTRIES, x->x_map.nomap); nle5 = atom_getfloatarg(5, MAXENTRIES, x->x_map.nomap); nle6 = atom_getfloatarg(6, MAXENTRIES, x->x_map.nomap); nle7 = atom_getfloatarg(7, MAXENTRIES, x->x_map.nomap); nle8 = atom_getfloatarg(8, MAXENTRIES, x->x_map.nomap); nle9 = atom_getfloatarg(9, MAXENTRIES, x->x_map.nomap); post("mode = %f, max = %f", x->mode, x->max); post("first 10 elements = %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", ele0, ele1, ele2, ele3, ele4, ele5, ele6, ele7, ele8, ele9); post("first 10 elements = %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", nle0, nle1, nle2, nle3, nle4, nle5, nle6, nle7, nle8, nle9); } void *sieve_new(t_floatarg f) { t_sieve *x = (t_sieve *)pd_new(sieve_class); x->mode = f; x->max = 0; x->outmap = 0; int i; for(i=0;ix_map.map+i, 0); SETFLOAT(x->x_map.nomap+i, 1); } x->mapped = outlet_new(&x->x_obj, &s_float); x->value = outlet_new(&x->x_obj, &s_float); x->mapout = outlet_new(&x->x_obj, &s_list); x->inst = outlet_new(&x->x_obj, &s_bang); return (void *)x; } void sieve_setup(void) { sieve_class = class_new(gensym("sieve"), (t_newmethod)sieve_new, 0, sizeof(t_sieve), 0, A_DEFFLOAT, 0); post("|^^^^^^^^^^^^^sieve^^^^^^^^^^^^^|"); post("|->^^^integer map to floats^^^<-|"); post("|^^^^^^^Edward Kelly 2006^^^^^^^|"); class_addfloat(sieve_class, sieve_float); class_addmethod(sieve_class, (t_method)sieve_set, gensym("set"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_map, gensym("map"), A_GIMME, 0); class_addmethod(sieve_class, (t_method)sieve_clear, gensym("clear"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_get, gensym("get"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_delete, gensym("delete"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_shunt, gensym("shunt"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_shift, gensym("shift"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_insert, gensym("insert"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_mode, gensym("mode"), A_DEFFLOAT, 0); class_addmethod(sieve_class, (t_method)sieve_debug, gensym("debug"), A_DEFFLOAT, 0); }