From d2eec74a4d8c21aad495ba61539486b24d7ab8dc Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Wed, 9 Oct 2002 10:19:04 +0000 Subject: moved from zexy/zexy to zexy svn path=/trunk/externals/zexy/; revision=169 --- src/z_random.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/z_random.c (limited to 'src/z_random.c') diff --git a/src/z_random.c b/src/z_random.c new file mode 100644 index 0000000..9a4bb9e --- /dev/null +++ b/src/z_random.c @@ -0,0 +1,143 @@ + +/* 1008:forum::für::umläute:2001 */ + +/* + urn : "generate random numbers without duplicates" + very max-like +*/ + +#include "zexy.h" + +/* ------------------------- urn ------------------------------- */ + +static t_class *urn_class; + +typedef struct _urn +{ + t_object x_obj; + unsigned int x_seed; /* the seed of the generator */ + + unsigned int x_range; /* max. random-number + 1 */ + unsigned int x_count; /* how many random numbers have we generated ? */ + char *x_state; /* has this number been generated already ? */ + + t_outlet *x_floatout, *x_bangout; + char x_noauto; +} t_urn; + +static int makeseed(void) +{ + static unsigned int random_nextseed = 1489853723; + random_nextseed = random_nextseed * 435898247 + 938284287; + return (random_nextseed & 0x7fffffff); +} + +static void makestate(t_urn *x, unsigned int newrange) +{ + if (x->x_range == newrange)return; + + if (x->x_range && x->x_state) { + freebytes(x->x_state, sizeof(char)*x->x_range); + x->x_state=0; + } + + x->x_range=newrange; + x->x_state=getbytes(sizeof(char)*x->x_range); +} + +static void urn_clear(t_urn *x) +{ + unsigned int i=x->x_range; + char *dummy=x->x_state; + if (!dummy || !i)return; + while(i--)*dummy++=0; + x->x_count=0; +} +static void urn_bang(t_urn *x) +{ + int range = (x->x_range<1?1:x->x_range); + unsigned int randval = x->x_seed; + + int nval, used=1; + + if (x->x_count>=range){ + outlet_bang(x->x_bangout); + if (x->x_noauto)return; + urn_clear(x); + } + + while (used) { + randval = randval * 472940017 + 832416023; + nval = ((double)range) * ((double)randval) + * (1./4294967296.); + if (nval >= range) nval = range-1; + used=x->x_state[nval]; + } + + x->x_count++; + x->x_state[nval]=1; + x->x_seed = randval; + outlet_float(x->x_floatout, nval); +} + +static void urn_flt2(t_urn *x, t_float f) +{ + unsigned int range = (f<1)?1:f; + makestate(x, range); + urn_clear(x); +} + + +static void urn_seed(t_urn *x, t_float f) +{ + x->x_seed = f; +} + +static void *urn_new(t_symbol *s, int argc, t_atom *argv) +{ + t_urn *x = (t_urn *)pd_new(urn_class); + + t_float f=0.; + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + x->x_floatout=outlet_new(&x->x_obj, &s_float); + x->x_bangout =outlet_new(&x->x_obj, &s_bang); + + x->x_seed = makeseed(); + x->x_noauto = 0; + + while(argc--){ + if (argv->a_type==A_SYMBOL) { + if (atom_getsymbol(argv)==gensym("no_auto")) { + x->x_noauto=1; + } + } else f = atom_getfloat(argv); + argv++; + } + + if (f<1.0)f=1.0; + makestate(x, f); + x->x_range = f; + urn_clear(x); + + return (x); +} + +static void urn_setup(void) +{ + urn_class = class_new(gensym("urn"), (t_newmethod)urn_new, + 0, sizeof(t_urn), 0, A_GIMME, 0); + + class_addbang (urn_class, urn_bang); + class_addmethod(urn_class, (t_method)urn_clear, gensym("clear"), 0); + class_addmethod(urn_class, (t_method)urn_flt2, gensym(""), A_DEFFLOAT, 0); + class_addmethod(urn_class, (t_method)urn_seed, gensym("seed"), A_DEFFLOAT, 0); + + + class_sethelpsymbol(urn_class, gensym("zexy/urn")); +} + +void z_random_setup(void) +{ + urn_setup(); +} -- cgit v1.2.1