/** Performs symbolic mix of fluids in given target ratios. */ Fluid mix(Fluid[] fluid, double[] target) { assert fluid.length == target.length; // prune out zero-weights int numZeros = 0; for (int i = 0; i < fluid.length; i++) { if (target[i] == 0) { numZeros++; } } if (numZeros > 0) { Fluid[] _fluid = new Fluid[fluid.length - numZeros]; double[] _target = new double[fluid.length - numZeros]; int pos = 0; for (int i = 0; i < fluid.length; i++) { if (target[i] != 0) { _fluid[pos] = fluid[i]; _target[pos] = target[i]; pos++; } } fluid = _fluid; target = _target; } // if we're down to one fluid, return it if (fluid.length == 1) { return fluid[0]; } // normalize the targets double sum = 0; for (int i = 0; i < target.length; i++) { sum += target[i]; } for (int i = 0; i < target.length; i++) { target[i] /= sum; } // find depth of mixing tree that is needed to obtain // precision int depth = 0; int[] ratios = null; do { depth++; ratios = getRatios(depth, target); } while (ratios == null); assert depth < 32 : "Depth is " + depth + ", bigger than 32: bit-width issues."; // System.out.println("ratio (" + ratios.length + "): " + ratios[0] + ":" + ratios[1] + "; // depth=" + depth); // break up ratios into bins Stack[] bins = new Stack[depth + 1]; for (int i = 0; i < bins.length; i++) { bins[i] = new Stack(); } for (int i = 0; i < target.length; i++) { int mask = 1; for (int j = 0; j < depth; j++) { if ((mask & ratios[i]) != 0) { bins[j].push(fluid[i]); } mask = mask << 1; } } BasicFluid result = buildMixingTree(bins, depth); // this toggles a greedy evaluation instead of demand-driven result.ensureAvail(); return result; }
/** Dump dependency dot-graph to <filename>. */ public void dumpGraph(String filename) { BasicFluid.dumpGraph(filename); }