PsyBigFraction.java
package coneforest.psylla.core;
import coneforest.psylla.runtime.*;
import java.math.BigInteger;
/**
* The representation of {@code bigfraction}.
*/
@Type("bigfraction")
public final class PsyBigFraction
implements PsyRational
{
private final BigInteger numerator, denominator;
private PsyBigFraction(final BigInteger numerator, final BigInteger denominator)
{
this.numerator=numerator;
this.denominator=denominator;
}
/**
* TODO
*
* @param numerator the numerator.
* @param denominator the denominator.
*/
public static PsyRational of(final BigInteger numerator, final BigInteger denominator)
{
var x=numerator;
var y=denominator;
if(y.equals(BigInteger.ZERO))
throw new IllegalArgumentException();
if(y.compareTo(BigInteger.ZERO)<0)
{
x=x.negate();
y=y.negate();
}
if(x.compareTo(BigInteger.ZERO)<0)
x=x.negate();
while(x.compareTo(BigInteger.ZERO)!=0)
{
if(x.compareTo(y)>0)
{
final var t=x;
x=y;
y=t;
continue;
}
y=y.mod(x);
}
x=numerator.divide(y);
y=denominator.divide(y);
if(y.compareTo(BigInteger.ZERO)<0)
{
x=x.negate();
y=y.negate();
}
return y.equals(BigInteger.ONE)? PsyIntegral.of(x): new PsyBigFraction(x, y);
}
@Override
public double doubleValue()
{
// TODO ?
return numerator.doubleValue()/denominator.doubleValue();
}
@Override
public long longValue()
{
return (long)doubleValue();
}
@Override
public BigInteger bigIntegerValue()
{
return psyFloor().bigIntegerValue();
}
@Override
public PsyIntegral psyNumerator()
{
return PsyIntegral.of(numerator);
}
@Override
public PsyIntegral psyDenominator()
{
return PsyIntegral.of(denominator);
}
@Override
public PsyIntegral psyFloor()
{
return PsyIntegral.of(numerator.signum()<0?
numerator.divide(denominator).subtract(BigInteger.ONE):
numerator.divide(denominator));
}
@Override
public PsyIntegral psyCeiling()
{
return PsyIntegral.of(numerator.signum()<0?
numerator.divide(denominator):
numerator.divide(denominator).add(BigInteger.ONE));
}
@Override
public int intValue()
{
return (int)doubleValue();
}
@Override
public boolean isZero()
{
return false;
}
@Override
public PsyIntegral psyToIntegral()
{
return psyRound();
}
@Override
public PsyIntegral psyRound()
{
final var intpart=numerator.divide(denominator);
return PsyIntegral.of(numerator.subtract(
intpart.multiply(denominator)).shiftLeft(1).compareTo(denominator)<0?
intpart: intpart.add(BigInteger.ONE));
}
@Override
public PsyInteger psySignum()
{
return PsyInteger.of(numerator.signum());
}
@Override
public String toSyntaxString()
{
return String.format("%d:%d", numerator, denominator);
}
}