@Override public Object visit(RealBinaryExpression n, Void arg) { Double leftDouble = (Double) n.getLeftOperand().accept(this, null); Double rightDouble = (Double) n.getRightOperand().accept(this, null); double leftVal = leftDouble.doubleValue(); double rightVal = rightDouble.doubleValue(); Operator op = n.getOperator(); switch (op) { case DIV: return leftVal / rightVal; case MUL: return leftVal * rightVal; case MINUS: return leftVal - rightVal; case PLUS: return leftVal + rightVal; case REM: return leftVal % rightVal; case ATAN2: return Math.atan2(leftVal, rightVal); case COPYSIGN: return Math.copySign(leftVal, rightVal); case HYPOT: return Math.hypot(leftVal, rightVal); case IEEEREMAINDER: return Math.IEEEremainder(leftVal, rightVal); case MAX: return Math.max(leftVal, rightVal); case MIN: return Math.min(leftVal, rightVal); case NEXTAFTER: return Math.nextAfter(leftVal, rightVal); case POW: return Math.pow(leftVal, rightVal); case SCALB: return Math.scalb(leftVal, (int) rightVal); default: log.warn("IntegerBinaryExpression: unimplemented operator: " + op); return null; } }
@Override public Double next() { double diff = to - from; double next = from + diff * workingRandom.nextDouble(); if (next >= to) { // Rounding error occurred next = Math.nextAfter(next, Double.NEGATIVE_INFINITY); } return next; }
@Override public int compare(DataKeyValue o1, DataKeyValue o2) { int cmp; // ensure we have DataKeyValue objects... if (o1 == null) { return (o2 == null) ? 0 : -1; } if (o2 == null) { return 1; } // ensure we have matching column names... if (o1.column == null) { // value is meaningless if no column name... return (o2.column == null) ? 0 : -1; } cmp = o1.column.compareTo(o2.column); if (cmp != 0) { // column names do not match return cmp; } // ensure we have non-null values... if (o1.value == null) { return (o2.value == null) ? 0 : -1; } if (o2.value == null) { return 1; } cmp = o1.value.compareTo(o2.value); if (cmp == 0) { // common case... return 0; } // Argh! we need to deal with possible numeric representation // problems... ElementDataType dt = columnMap.get(o1.column); if (dt == ElementDataType.number) { // special case of numeric data. // !!Important!! Double.valueOf(str) handles NaN and +/-Infinity Double localNumber = Double.valueOf(o1.value); Double serverNumber = Double.valueOf(o2.value); if (localNumber.equals(serverNumber)) { // simple case -- trailing zeros or string representation mix-up // return 0; } else if (localNumber.isInfinite() && serverNumber.isInfinite()) { // if they are both plus or both minus infinity, we have a match if (Math.signum(localNumber) == Math.signum(serverNumber)) { return 0; } else { return (Math.signum(localNumber) < 0.0) ? -1 : 1; } } else if (localNumber.isNaN() && serverNumber.isNaN()) { // can't distinguish them... return 0; } else if (localNumber.isNaN()) { // NaN less than infinities... return -1; } else if (serverNumber.isNaN()) { return 1; } else if (localNumber.isInfinite()) { // infinity is high or low, based upon its sign return (Math.signum(localNumber) < 0.0) ? -1 : 1; } else if (serverNumber.isInfinite()) { return (Math.signum(serverNumber) < 0.0) ? 1 : -1; } else { double localDbl = localNumber; double serverDbl = serverNumber; if (localDbl == serverDbl) { // should handle two values like 9.80 and 9.8 // but equals() earlier should also handle this. return 0; } // We have two values that may be like: // 9.8+epsilon and 9.8 // consider them equal if they are within 2 steps of // each other. Deals with differing double-to-string // and string-to-double conversion libraries across // platforms and languages. double localNear = localDbl; int idist = 0; int idistMax = 2; for (idist = 0; idist < idistMax; ++idist) { localNear = Math.nextAfter(localNear, serverDbl); if (localNear == serverDbl) { break; } } if (idist < idistMax) { return 0; } return localNumber.compareTo(serverNumber); } } // otherwise, return whatever the string compare gave... return cmp; }
/** * Evolves the specified variables using the SBX operator. * * @param v1 the first variable * @param v2 the second variable * @param distributionIndex the distribution index of this SBX operator */ public void evolve(RealVariable v1, RealVariable v2, double distributionIndex) { double x0 = v1.getValue(); double x1 = v2.getValue(); double dx = Math.abs(x1 - x0); if (dx > Settings.EPS) { double lb = v1.getLowerBound(); double ub = v1.getUpperBound(); double bl; double bu; if (x0 < x1) { bl = 1 + 2 * (x0 - lb) / dx; bu = 1 + 2 * (ub - x1) / dx; } else { bl = 1 + 2 * (x1 - lb) / dx; bu = 1 + 2 * (ub - x0) / dx; } // use symmetric distributions if (bl < bu) { bu = bl; } else { bl = bu; } double p_bl = 1 - 1 / (2 * Math.pow(bl, distributionIndex + 1)); double p_bu = 1 - 1 / (2 * Math.pow(bu, distributionIndex + 1)); double u = pprng.nextDouble(); // prevent out-of-bounds values if PRNG draws the value 1.0 if (u == 1.0) { u = Math.nextAfter(u, -1.0); } double u0 = u * p_bl; double u1 = u * p_bu; double b0; double b1; if (u0 <= 0.5) { b0 = Math.pow(2 * u0, 1 / (distributionIndex + 1)); } else { b0 = Math.pow(0.5 / (1 - u0), 1 / (distributionIndex + 1)); } if (u1 <= 0.5) { b1 = Math.pow(2 * u1, 1 / (distributionIndex + 1)); } else { b1 = Math.pow(0.5 / (1 - u1), 1 / (distributionIndex + 1)); } if (x0 < x1) { v1.setValue(0.5 * (x0 + x1 + b0 * (x0 - x1))); v2.setValue(0.5 * (x0 + x1 + b1 * (x1 - x0))); } else { v1.setValue(0.5 * (x0 + x1 + b1 * (x0 - x1))); v2.setValue(0.5 * (x0 + x1 + b0 * (x1 - x0))); } // this makes PISA's SBX compatible with other implementations // which swap the values if (pprng.nextBoolean()) { double temp = v1.getValue(); v1.setValue(v2.getValue()); v2.setValue(temp); } // guard against out-of-bounds values if (v1.getValue() < lb) { v1.setValue(lb); } else if (v1.getValue() > ub) { v1.setValue(ub); } if (v2.getValue() < lb) { v2.setValue(lb); } else if (v2.getValue() > ub) { v2.setValue(ub); } } }
@MethodSubstitution(isStatic = true) static double nextAfter(double x, double d) { double xx = (x == -0.0 ? 0.0 : x); return Math.nextAfter(xx, d); }
static double nextAfter(double x, double d) { return Math.nextAfter(x, d); }
static double next2(double v) { return Math.nextAfter(v, 1.0); }