in src/main/java/org/apache/commons/imaging/common/RationalNumber.java [101:175]
public static RationalNumber valueOf(double value) {
if (value >= Integer.MAX_VALUE) {
return new RationalNumber(Integer.MAX_VALUE, 1);
}
if (value <= -Integer.MAX_VALUE) {
return new RationalNumber(-Integer.MAX_VALUE, 1);
}
boolean negative = false;
if (value < 0) {
negative = true;
value = Math.abs(value);
}
RationalNumber l;
RationalNumber h;
if (value == 0) {
return new RationalNumber(0, 1);
}
if (value >= 1) {
final int approx = (int) value;
if (approx < value) {
l = new RationalNumber(approx, 1);
h = new RationalNumber(approx + 1, 1);
} else {
l = new RationalNumber(approx - 1, 1);
h = new RationalNumber(approx, 1);
}
} else {
final int approx = (int) (1.0 / value);
if ((1.0 / approx) < value) {
l = new RationalNumber(1, approx);
h = new RationalNumber(1, approx - 1);
} else {
l = new RationalNumber(1, approx + 1);
h = new RationalNumber(1, approx);
}
}
Option low = Option.factory(l, value);
Option high = Option.factory(h, value);
Option bestOption = (low.error < high.error) ? low : high;
final int maxIterations = 100; // value is quite high, actually.
// shouldn't matter.
for (int count = 0; bestOption.error > TOLERANCE
&& count < maxIterations; count++) {
final RationalNumber mediant = RationalNumber.factoryMethod(
low.rationalNumber.numerator + high.rationalNumber.numerator,
low.rationalNumber.divisor + high.rationalNumber.divisor);
final Option mediantOption = Option.factory(mediant, value);
if (value < mediant.doubleValue()) {
if (high.error <= mediantOption.error) {
break;
}
high = mediantOption;
} else {
if (low.error <= mediantOption.error) {
break;
}
low = mediantOption;
}
if (mediantOption.error < bestOption.error) {
bestOption = mediantOption;
}
}
return negative ? bestOption.rationalNumber.negate()
: bestOption.rationalNumber;
}