1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
/*
(c) 2002:cxc@web.fm
randomix: various PRNG's
code taken from: http://remus.rutgers.edu/%7Erhoads/Code/code.html
let's check it out
*/
#include <m_pd.h>
#include <stdlib.h>
#include <math.h>
#define SMALLEST_RANGE .0001
#ifndef RAND_MAX
#define RAND_MAX 2147483647
#endif
static int makeseed(void)
{
static unsigned int random1_nextseed = 1489853723;
random1_nextseed = random1_nextseed * 435898247 + 938284287;
return (random1_nextseed & 0x7fffffff);
}
static int rand_random_fl(int seed) {
int q;
double state;
/* The following parameters are recommended settings based on research
uncomment the one you want. */
double a = 1389796, m = RAND_MAX;
/* static double a = 950975, m = 2147483647; */
/* static double a = 3467255, m = 21474836472; */
/* static double a = 657618, m = 4294967291; */
/* static double a = 93167, m = 4294967291; */
/* static double a = 1345659, m = 4294967291; */
state = seed;
state *= a;
q = state / m;
state -= q*m;
return state;
}
/* -------------------------- dist_normal ------------------------------ */
/* Generate a normal random variable with mean 0 and standard deviation
of 1. To adjust to some other distribution, multiply by the standard
deviation and add the mean. Box-Muller method
note: rand() is a function that returns a uniformly distributed random
number from 0 to RAND_MAX
*/
static t_class *dist_normal_class;
typedef struct _dist_normal
{
t_object x_obj;
t_float x_mn; // mean
t_float x_dv; // deviation
t_float x_u1;
t_float x_u2;
t_float x_f; // lower limit
t_float x_g; // upper limit
unsigned int x_state; // current seed
} t_dist_normal;
static void *dist_normal_new(t_floatarg mn, t_floatarg dv)
{
t_dist_normal *x = (t_dist_normal *)pd_new(dist_normal_class);
x->x_mn = (mn) ? mn : 0;
x->x_dv = (dv) ? dv : 1;
x->x_u1 = 13;
x->x_u2 = 1000;
x->x_f = 0;
x->x_g = RAND_MAX;
//post("cxc/randomix.c: lolim: %f - %f, uplim: %f - %f", x->x_f, f, x->x_g, g);
x->x_state = makeseed();
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("fl1"));
// inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("fl2"));
//outlet_new(&x->x_obj, &s_float);
outlet_new(&x->x_obj, 0);
return (x);
}
static double dist_normal_rand(t_dist_normal *x)
{
int n = x->x_f;
double nval;
double m;
m = (double)RAND_MAX * 2;
// post("cxc/randomix.c: x_state: %d",x->x_state);
x->x_state = rand_random_fl(x->x_state);
//nval = ((double)x->x_state / m) * (double)(x->x_g - x->x_f) + (double)x->x_f;
nval = (double)x->x_state;
return (nval);
}
static void dist_normal_doit(t_dist_normal *x)
{
static double V2, fac;
static int phase = 0;
double S, Z, U1, U2, V1;
if (phase)
Z = V2 * fac;
else
{
do {
/* U1 = (double)rand() / RAND_MAX; */
/* U2 = (double)rand() / RAND_MAX; */
U1 = (double)dist_normal_rand(x) / RAND_MAX;
U2 = (double)dist_normal_rand(x) / RAND_MAX;
// post("cxc/randomix.c: test %f %f %f %f", x->x_u1, x->x_u2, U1, U2);
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1);
fac = sqrt (-2 * log(S) / S);
Z = V1 * fac;
}
phase = 1 - phase;
//return Z;
outlet_float(x->x_obj.ob_outlet, Z);
}
static void dist_normal_bang(t_dist_normal *x)
{
/* post("cxc/randomix.c: dist_normal banged"); */
/* post("cxc/randomix.c: RAND_MAX: %d",RAND_MAX); */
/* post("cxc/randomix.c: test: %f %f", x->x_u1, x->x_u2); */
dist_normal_doit(x);
}
void dist_normal_low(t_dist_normal *x, t_floatarg mn)
{
x->x_mn = mn;
}
void dist_normal_upp(t_dist_normal *x, t_floatarg dv)
{
x->x_dv = dv;
}
void dist_normal_float(t_dist_normal *x, t_floatarg r)
{
outlet_float(x->x_obj.ob_outlet, r);
}
void dist_normal_list(t_dist_normal *x, t_symbol *s, int argc, t_atom *argv)
{
outlet_list(x->x_obj.ob_outlet, s, argc, argv);
}
void dist_normal_setup(void)
{
dist_normal_class = class_new(gensym("dist_normal"), (t_newmethod)dist_normal_new, 0,
sizeof(t_dist_normal), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
class_addbang(dist_normal_class, dist_normal_bang);
class_addmethod(dist_normal_class, (t_method)dist_normal_low, gensym("fl1"), A_FLOAT, 0);
// class_addmethod(dist_normal_class, (t_method)dist_normal_upp, gensym("fl2"), A_FLOAT, 0);
class_addlist (dist_normal_class, dist_normal_list);
/* class_addmethod(dist_normal_class, (t_method)dist_normal_seed, */
/* gensym("seed"), A_FLOAT, 0); */
}
|