Package jmathexpr.arithmetic.rational.impl

Source Code of jmathexpr.arithmetic.rational.impl.LongRationalNumber

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.arithmetic.rational.impl;

import java.math.BigInteger;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.Numbers;
import jmathexpr.arithmetic.integer.impl.LongIntegerNumber;
import jmathexpr.arithmetic.natural.NaturalNumber;
import jmathexpr.arithmetic.natural.impl.LongNaturalNumber;
import jmathexpr.arithmetic.rational.RationalNumber;
import jmathexpr.arithmetic.real.RealNumber;
import jmathexpr.arithmetic.real.impl.DoubleRealNumber;

/**
* Rational number implementation based on two Java long value (separate value
* for the numerator and the denominator).
*
* @author Elemér Furka
*/
public class LongRationalNumber extends RationalNumber {
   
    final long numerator;
    final long denominator;
   
    public LongRationalNumber(long numerator, long denominator) {
        if (denominator <= 0) {
            throw new IllegalArgumentException("Illegal denominator: " + denominator);
        }
       
        this.numerator = numerator;
        this.denominator = denominator;
    }
   
    @Override
    public RationalNumber evaluate() {
        LongRationalNumber simplified = simplify();
       
        if (simplified.denominator == 1) {
            return new LongIntegerNumber(simplified.numerator);
        }
        else {
            return simplified;
        }
    }
   
    @Override
    public LongIntegerNumber numerator() {
        return new LongIntegerNumber(numerator);
    }
   
    @Override
    public LongNaturalNumber denominator() {
        return new LongNaturalNumber(denominator);
    }
   
    private LongRationalNumber simplify() {
        long gcd = gcd(numerator, denominator);
       
        return gcd > 1 ? new LongRationalNumber(numerator / gcd, denominator / gcd) : this;
    }
   
    @Override
    public ANumber add(ANumber addend) {
        if (addend instanceof LongRationalNumber) {
            LongRationalNumber other = (LongRationalNumber) addend;
            long gcd = gcd(denominator, other.denominator);
            long lcm = denominator * other.denominator / gcd;
           
            return new LongRationalNumber(numerator * (lcm / denominator) + other.numerator * (lcm / other.denominator), lcm).evaluate();
        } else {
            return Numbers.add(this, addend);
        }
    }
   
    private static long gcd(long long1, long long2) {
        return BigInteger.valueOf(long1).gcd(BigInteger.valueOf(long2)).longValue();
    }
   
    @Override
    public ANumber subtract(ANumber subtrahend) {
        if (subtrahend instanceof LongRationalNumber) {
            LongRationalNumber other = (LongRationalNumber) subtrahend;
            long gcd = gcd(denominator, other.denominator);
            long lcm = denominator * other.denominator / gcd;
           
            return new LongRationalNumber(numerator * (lcm / denominator) - other.numerator * (lcm / other.denominator), lcm).evaluate();
        } else {
            return Numbers.subtract(this, subtrahend);
        }
    }
   
    @Override
    public ANumber multiply(ANumber multiplier) {
        if (multiplier instanceof LongRationalNumber) {
            LongRationalNumber other = (LongRationalNumber) multiplier;
           
            return new LongRationalNumber(numerator * other.numerator, denominator * other.denominator).evaluate();
        } else {
            return Numbers.multiply(this, multiplier);
        }
    }
   
    @Override
    public ANumber divide(ANumber divisor) {
        if (divisor instanceof LongRationalNumber) {
            LongRationalNumber other = (LongRationalNumber) divisor;
           
            if (other.numerator != 0) {
                long denom = denominator * other.numerator;
               
                return denom > 0 ?
                        new LongRationalNumber(numerator * other.denominator, denom).evaluate()
                      : new LongRationalNumber(-numerator * other.denominator, -denom).evaluate();
            } else {
                throw new UnsupportedOperationException(
                        String.format("Division by 0: %s / %s", this, other));
            }
        } else {
            return Numbers.divide(this, divisor);
        }
    }

    @Override
    public LongRationalNumber negate() {
        return new LongRationalNumber(-numerator, denominator);
    }

    @Override
    public boolean equals(Object object) {
        if (object == null) return false;
        if (this == object) return true;
        if (object instanceof LongRationalNumber) {
            LongRationalNumber simplified = simplify();
            LongRationalNumber other = ((LongRationalNumber) object).simplify();
           
            return simplified.numerator == other.numerator && simplified.denominator == other.denominator;
        }
       
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 13 * hash + (int) (this.numerator ^ (this.numerator >>> 32));
        hash = 13 * hash + (int) (this.denominator ^ (this.denominator >>> 32));
        return hash;
    }
   
    @Override
    public String toString() {
        return String.format("%d/%d", numerator, denominator);
    }

    @Override
    public boolean isNatural() {
        LongRationalNumber simplified = simplify();
       
        return simplified.numerator >= 0 && simplified.denominator == 1;
    }

    @Override
    public boolean isInteger() {
        LongRationalNumber simplified = simplify();
       
        return simplified.denominator == 1;
    }

    @Override
    public boolean isNegative() {
        return numerator < 0;
    }

    @Override
    public boolean isZero() {
        return numerator == 0;
    }

    @Override
    public boolean isOne() {
        return numerator == denominator;
    }

    @Override
    public ANumber pow(ANumber exponent) {
        if (exponent instanceof NaturalNumber) {
            LongRationalNumber simplified = simplify();
            LongRationalNumber pown =
                    (LongRationalNumber) new LongIntegerNumber(simplified.numerator).pow(exponent).toRational();
            LongRationalNumber powd =
                    (LongRationalNumber) new LongIntegerNumber(simplified.denominator).pow(exponent).toRational();
           
            return new LongRationalNumber(pown.numerator, powd.numerator);
        } else {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    }

    @Override
    public RealNumber toReal() {
        return new DoubleRealNumber(((double) numerator) / denominator);
    }

    @Override
    public boolean le(ANumber expr) {
        if (expr instanceof LongRationalNumber) {
            ANumber diff = subtract((LongRationalNumber) expr);
           
            return diff.isNegative() || diff.isZero();
        } else {
            throw new IllegalArgumentException(expr.getClass() + " Expected: LongRationalNumber");
        }
    }

    @Override
    public boolean lt(ANumber expr) {
        if (expr instanceof LongRationalNumber) {
            ANumber diff = subtract((LongRationalNumber) expr);
           
            return diff.isNegative();
        } else {
            throw new IllegalArgumentException(expr.getClass() + " Expected: LongRationalNumber");
        }
    }
}
TOP

Related Classes of jmathexpr.arithmetic.rational.impl.LongRationalNumber

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.