/*
This code is a a heavily modified version of Numbers from Rich Hickeys clojure core, see Numbers.java for copyright
*/
package com.googlecode.totallylazy.numbers;
import java.math.BigDecimal;
import java.math.BigInteger;
public final class RatioOperators implements Operators<Ratio> {
public static RatioOperators Instance = new RatioOperators();
private RatioOperators() {}
public final Class<Ratio> forClass() {
return Ratio.class;
}
public final int priority() {
return 5;
}
@Override
public Number absolute(Ratio value) {
return isNegative(value) ? negate(value) : value ;
}
public final Number negate(Ratio value) {
return new Ratio(value.numerator.negate(), value.denominator);
}
public final Number increment(Ratio value) {
return Numbers.add(value, 1);
}
public final Number decrement(Ratio value) {
return Numbers.add(value, -1);
}
public final boolean isZero(Ratio value) {
return value.numerator.signum() == 0;
}
public final boolean isPositive(Ratio value) {
return value.numerator.signum() > 0;
}
public final boolean isNegative(Ratio value) {
return value.numerator.signum() < 0;
}
public final boolean equalTo(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
return rx.numerator.equals(ry.numerator)
&& rx.denominator.equals(ry.denominator);
}
public final boolean lessThan(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
return Numbers.lessThan(rx.numerator.multiply(ry.denominator), ry.numerator.multiply(rx.denominator));
}
public final Number add(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
return divide(ry.numerator.multiply(rx.denominator)
.add(rx.numerator.multiply(ry.denominator))
, ry.denominator.multiply(rx.denominator));
}
public final Number multiply(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
return Numbers.divide(ry.numerator.multiply(rx.numerator)
, ry.denominator.multiply(rx.denominator));
}
public final Number divide(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
return Numbers.divide(ry.denominator.multiply(rx.numerator)
, ry.numerator.multiply(rx.denominator));
}
public final Number quotient(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
BigInteger q = rx.numerator.multiply(ry.denominator).divide(
rx.denominator.multiply(ry.numerator));
return Numbers.reduce(q);
}
public final Number remainder(Number x, Number y) {
Ratio rx = toRatio(x);
Ratio ry = toRatio(y);
BigInteger q = rx.numerator.multiply(ry.denominator).divide(
rx.denominator.multiply(ry.numerator));
return Numbers.subtract(x, Numbers.multiply(q, y));
}
public static Ratio toRatio(Number value) {
if (value instanceof Ratio)
return (Ratio) value;
else if (value instanceof BigDecimal) {
BigDecimal bx = (BigDecimal) value;
BigInteger bv = bx.unscaledValue();
int scale = bx.scale();
if (scale < 0)
return new Ratio(bv.multiply(BigInteger.TEN.pow(-scale)), BigInteger.ONE);
else
return new Ratio(bv, BigInteger.TEN.pow(scale));
}
return new Ratio(BigIntegerOperators.bigInteger(value), BigInteger.ONE);
}
}