package mikera.randomz;

import mikera.util.Rand;

public final class ProbabilityPicker {
	private static final double[] NULLCHANCES=new double[0];
	private static final Object[] NULLOBJECTS=new Object[0];
	
	private int count=0;
	private double[] chances=NULLCHANCES;
	private double[] belows=NULLCHANCES;
	private Object[] objects=NULLOBJECTS;
	private double total=0.0;
	
	/**
	 * Picks a random object
	 * 
	 * @return Random object chosen with associated relative probability
	 */
	@SuppressWarnings("unchecked")
	public O pick() {
		double r=Rand.nextDouble()*total;
		
		int i=0;
		int ir=1;
		for (;;) {
			double ci=chances[i];
			if (rchances.length) {
			int nn=Math.max(n,(chances.length*2));
			double[] newChances=new double[nn];
			double[] newBelows=new double[nn];
			Object[] newObjects=new Object[nn];

			System.arraycopy(chances, 0, newChances,0,count);
			System.arraycopy(belows, 0, newBelows,0, count);
			System.arraycopy(objects, 0, newObjects,0,count);
			
			chances=newChances;
			objects=newObjects;
			belows=newBelows;
		}
	}
	
	
	public void add(O object, double probability) {
		int i=getIndex(object);
		if (i<0) {
			addNew(object,probability);
			return;
		}
		setChance(i,probability+chances[i]);
	}
	
	private void addNew(O object, double probability) {
		if (probability<0) return;
		
		ensureSize(count+1);
		
		int i=count;
		count++;
		
		objects[i]=object;

		setChance(i,probability);		
	}
	
	public int getIndex(O o) {
		for (int i=0; i1) {
			int pi=parentIndex(i,r);
			int pr=r/2; // parent order
			
			if (((i+1)&pr)>0) {
				// top branch
			} else {
				// update below
				belows[pi]+=d;
			}
			
			r=pr;
			i=pi;
		}
	}
	
	public double getTotal() {
		return total;
	}
	
	public int getCount() {
		return count;
	}
	
	@SuppressWarnings("unchecked")
	public void remove(Object object) {
		O o=(O)object;
		int i=getIndex(o);
		if (i<0) throw new Error("Object not found: "+object.toString());
		remove(i);
	}
		
	private void remove(int i) {
		setChance(i,0);
		int last=count-1;
		
		if (i>1) ) -1;
	}
	
	public static int childIndex(int i, int branch) {
		return childIndex(i,order(i),branch);
	}
	
	private static int childIndex(int i, int ir, int branch) {
		return i+(1+branch)*ir;
	}
	
	private static int fillBitsRight(int n) {
		// TODO: use bitwise ops from mikera
		n = n | (n >> 1);
		n = n | (n >> 2);
		n = n | (n >> 4);
		n = n | (n >> 8);
		n = n | (n >> 16);
		return n;
	}
	
	private static int roundUpToPowerOfTwo(int n) {
		// TODO: use bitwise ops from mikera
		n = n - 1;
		n = fillBitsRight(n);
		n = n + 1;
		return n;
	}
	
	public static int order(int i) {
		return roundUpToPowerOfTwo(i+2)/2;
	}
}

 

Ads help maintain this website.