private void divideByGCD() { if (weights.size() > 0) { int d = gcd(weights.get(0).getIntegerMass(), weights.get(1).getIntegerMass()); for (int i = 2; i < weights.size(); ++i) { d = gcd(d, weights.get(i).getIntegerMass()); if (d == 1) return; } precision *= d; for (ChemicalElement weight : weights) { weight.setIntegerMass(weight.getIntegerMass() / d); } } }
private void computeLCMs() { final ChemicalElement first = weights.get(0); first.setL(1); first.setLcm(first.getIntegerMass()); for (int i = 1; i < weights.size(); i++) { final ChemicalElement weight = weights.get(i); int temp = first.getIntegerMass() / gcd(first.getIntegerMass(), weight.getIntegerMass()); weight.setL(temp); weight.setLcm(temp * weight.getIntegerMass()); } }
DecompIterator(int[][] ERT, int minIntegerMass, int maxIntegerMass, double minDoubleMass, double maxDoubleMass, int[] minValues, int[] maxValues, List<ChemicalElement> weights) { this.ERT = ERT; this.minDoubleMass = minDoubleMass; this.maxDoubleMass = maxDoubleMass; this.buffer = new int[weights.size()]; if (minValues != null) { boolean allZero = true; for (int k : minValues) if (k > 0) allZero = false; if (!allZero) this.minValues = minValues; else this.minValues = null; } else this.minValues = null; this.maxValues = maxValues; this.weights = weights; k = weights.size(); j = new int[k]; m = new int[k]; lbound = new int[k]; r = new int[k]; flagWhile = false; // flag whether we are in the while-loop or not a = weights.get(0).getIntegerMass(); // Init for (int i = 1; i < k; ++i) { lbound[i] = Integer.MAX_VALUE; // this is just to ensure, that lbound < m in the first iteration } i = k - 1; m[i] = maxIntegerMass; // m[i] corresponds to M, m[i-1] ^= m this.rewind = false; this.deviation = maxIntegerMass - minIntegerMass; this.ERTdev = Integer.highestOneBit(deviation); }
private void computeErrors() { this.minError = 0d; this.maxError = 0d; for (ChemicalElement weight : weights) { final double error = (precision * weight.getIntegerMass() - weight.getMass()) / weight.getMass(); minError = Math.min(minError, error); maxError = Math.max(maxError, error); } }
private void calcERT() { int firstLongVal = weights.get(0).getIntegerMass(); int[][] ERT = new int[firstLongVal][weights.size()]; int d, r, n, argmin; d = gcd(firstLongVal, weights.get(j).getIntegerMass()); for (int p = 0; p < d; p++) { // Need to start d Round Robin loops if (p == 0) { n += weights.get(j).getIntegerMass(); if (n < 0) { throw new ArithmeticException("Integer overflow occurs. DECOMP cannot calculate decompositions for the given alphabet as it exceeds the 32 bit integer space. Please use a smaller precision value.");
/** * Check if a mass is decomposable. This is done in constant time (especially: it is very very very fast!). * But it doesn't check if there is a valid decomposition. Therefore, even if the method returns true, * all decompositions may be invalid for the given validator or given bounds. * #decompose(mass) uses this function before starting the decomposition, therefore this method should only * be used if you don't want to start the decomposition algorithm. * * @return true if the mass is decomposable, ignoring bounds or any additional filtering rule */ boolean maybeDecomposable(double from, double to) { init(); final int[][][] ERTs = this.ERTs; final int[] minmax = new int[2]; //normal version seems to be faster, because it returns after first hit integerBound(from, to, minmax); final int a = weights.get(0).getIntegerMass(); for (int i = minmax[0]; i <= minmax[1]; ++i) { final int r = i % a; if (i >= ERTs[0][r][weights.size() - 1]) return true; } return false; }
if (j[i] < weights.get(i).getL() && m[i] - j[i] * weights.get(i).getIntegerMass() >= 0) { buffer[i] = j[i]; m[i - 1] = m[i] - j[i] * weights.get(i).getIntegerMass(); r[i] = m[i - 1] % a;