# key/value array of known size define(_size,0) define(_val,-1*$1) define(_key,$1) # iterator for storing n samples from a distribution in a working memory (wme) define(InitVars,`wme,n, nums,i') define(init1,` delete nums; for(i=1;i<=n;i++) nums[i] = $2 + (rand()*Tiny); nums2cdf(nums,wme,n,$1)') ########################################################################## BEGIN {Tiny=10^(-10); Small=Tiny*10 } function nums2cdf(nums,cdf,n,key, min,max,i,j,one,sum,before) { min= 10^32; max= -1 * max; # find min, max for(i=1;i<=n;i++) { one = nums[i] max = one > max ? one : max; min = one < min ? one : min; } # sum the curve for(i=1;i<=n;i++) { one = (nums[i] - min)/ (max - min); sum += one; } # generate cdf before=0 asort(nums); # sorts min to max, so we'll run it backwards for(i=n;i>=1;i--) { j = n - i + 1; cdf[key,_val(j)] = int(nums[i]/Small) *Small; cdf[key,_key(j)] = 1 - before; # store cdf at i one = ((nums[i] - min)/ (max - min))/sum; before += one } cdf[key, _size] = n } function pick(w,key, i,want,left,right,mid,most,min,max) { # bin chop most = w[key,_size]; want = rand(); left = 1; right= most; while(left < right) { mid = int((left+right)/2); want < w[key,mid] ? left = mid+1 : right=mid } if (left==1) {min=1; max=2} else {min=left-1; max=left}; min = w[key, _val(min)] max = w[key, _val(max)] return between(min,max) } function round(x) { return int( x + ((x < 0) ? -0.5 : 0.5)) } function between(min,max) { return (max < min) ? between(max,min) : min+ ((max-min)*rand())} function ratio(min,max) { return between(min,max) } function nominal(range) { return ordinal(range) } function ordinal(range) { return range[ratioInt(1,range[0])] } function normalInt(m,s) { return int(normal(m,s)) } function normal(m,s) { return m+box_muller()*s } function ratioInt(min,max, aLittle) { if(min==max) return min; aLittle = 0.499999; min=min - aLittle; max=max + aLittle; return round(between(min,max)); } function box_muller(m,s, n,x1,x2,w) { w=1; while (w >= 1) { x1= 2.0 * rand() - 1; x2= 2.0 * rand() - 1; w = x1*x1 + x2*x2}; w = sqrt((-2.0 * log(w))/w); return x1 * w; } function indexOf(x,range,i) { for(i in range) if (i > 0 ) if (range[i]==x) return i; bad(x " not in range \n"); } BEGIN { srand(Seed ? Seed : 1)} function inits(InitVars) { init1("age", normalInt(100,10) ) init1("weight",normal(10,1) ) }