All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.redberry.core.number.Rational Maven / Gradle / Ivy

Go to download

Redberry is an open source computer algebra system designed for tensor manipulation. It implements basic computer algebra system routines as well as complex tools for real computations in physics. This is Redberry core, which contains the implementation of the basic computer algebra routines and general-purpose transformations.

The newest version!
/*
 * Redberry: symbolic tensor computations.
 *
 * Copyright (c) 2010-2015:
 *   Stanislav Poslavsky   
 *   Bolotin Dmitriy       
 *
 * This file is part of Redberry.
 *
 * Redberry is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Redberry is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Redberry. If not, see .
 */
package cc.redberry.core.number;

import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.fraction.BigFraction;
import org.apache.commons.math3.fraction.FractionConversionException;

import java.io.Serializable;
import java.math.BigInteger;

import static cc.redberry.core.number.NumberUtils.*;

/**
 * Representation of a rational number without any overflow. This class is a
 * wrapper of {@link BigInteger}.
 * 

*

This class implements mathematical operations declared in * {@link cc.redberry.core.number.Number} as operations with in the following * way. If argument is {@link Numeric}, the result will be {@code Numeric} too. * For example, 2 / 3 +1.0 will give 1.666666 and so on. If argument is {@code Rational} * number, the result will be {@code Rational} too. * * @author Stanislav Poslavsky * @see Number * @see Numeric * @see BigFraction */ public final class Rational extends Real implements Serializable { /** * A fraction representing "2 / 1". */ public static final Rational TWO = new Rational(2); /** * A fraction representing "4 / 1". */ public static final Rational FOUR = new Rational(4); /** * A fraction representing "-2 / 1". */ public static final Rational MINUS_TWO = new Rational(-2); /** * A fraction representing "1". */ public static final Rational ONE = new Rational(1); /** * A fraction representing "0". */ public static final Rational ZERO = new Rational(0); /** * A fraction representing "-1 / 1". */ public static final Rational MINUS_ONE = new Rational(-1); /** * A fraction representing "4/5". */ public static final Rational FOUR_FIFTHS = new Rational(4, 5); /** * A fraction representing "1/5". */ public static final Rational ONE_FIFTH = new Rational(1, 5); /** * A fraction representing "1/2". */ public static final Rational ONE_HALF = new Rational(1, 2); /** * A fraction representing "1/2". */ public static final Rational MINUSE_ONE_HALF = new Rational(-1, 2); /** * A fraction representing "1/4". */ public static final Rational ONE_QUARTER = new Rational(1, 4); /** * A fraction representing "1/3". */ public static final Rational ONE_THIRD = new Rational(1, 3); /** * A fraction representing "3/5". */ public static final Rational THREE_FIFTHS = new Rational(3, 5); /** * A fraction representing "3/4". */ public static final Rational THREE_QUARTERS = new Rational(3, 4); /** * A fraction representing "2/5". */ public static final Rational TWO_FIFTHS = new Rational(2, 5); /** * A fraction representing "2/3". */ public static final Rational TWO_THIRDS = new Rational(2, 3); public static final BigFraction BIG_FRACTION_MAX_DOUBLE = new BigFraction(Double.MAX_VALUE); public static final BigFraction BIG_FRACTION_MIN_DOUBLE = new BigFraction(-Double.MAX_VALUE); public static final BigFraction BIG_FRACTION_MAX_INTEGER = new BigFraction(Integer.MAX_VALUE); public static final BigFraction BIG_FRACTION_MIN_INTEGER = new BigFraction(Integer.MIN_VALUE); public static final BigFraction BIG_FRACTION_MAX_LONG = new BigFraction(Long.MAX_VALUE); public static final BigFraction BIG_FRACTION_MIN_LONG = new BigFraction(Long.MIN_VALUE); /** * Serializable version identifier. */ private static final long serialVersionUID = -5630213147331578515L; /* * rational value */ private final BigFraction fraction; public Rational(BigFraction fraction) { checkNotNull(fraction); this.fraction = fraction; } /** * @see BigFraction#BigFraction(java.math.BigInteger) */ public Rational(BigInteger num) { checkNotNull(num); fraction = new BigFraction(num); } /** * @see BigFraction#BigFraction(java.math.BigInteger, java.math.BigInteger) */ public Rational(BigInteger num, BigInteger den) { checkNotNull(num); checkNotNull(den); fraction = new BigFraction(num, den); } /** * @see BigFraction#BigFraction(double) */ public Rational(double value) throws MathIllegalArgumentException { fraction = new BigFraction(value); } /** * @see BigFraction#BigFraction(double, double, int) */ public Rational(double value, double epsilon, int maxIterations) throws FractionConversionException { fraction = new BigFraction(value, epsilon, maxIterations); } /** * @see BigFraction#BigFraction(double, int) */ public Rational(double value, int maxDenominator) throws FractionConversionException { fraction = new BigFraction(value, maxDenominator); } /** * @see BigFraction#BigFraction(int) */ public Rational(int num) { fraction = new BigFraction(num); } /** * @see BigFraction#BigFraction(int, int) */ public Rational(int num, int den) { fraction = new BigFraction(num, den); } /** * @see BigFraction#BigFraction(long) */ public Rational(long num) { fraction = new BigFraction(num); } /** * @see BigFraction#BigFraction(long, long) */ public Rational(long num, long den) { fraction = new BigFraction(num, den); } public BigFraction getBigFraction() { return fraction; } @Override public long longValue() { if (fraction.compareTo(BIG_FRACTION_MAX_LONG) > 0 || fraction.compareTo(BIG_FRACTION_MIN_LONG) < 0) throw new RuntimeException("Long overflow."); return fraction.longValue(); } @Override public int intValue() { if (fraction.compareTo(BIG_FRACTION_MAX_INTEGER) > 0 || fraction.compareTo(BIG_FRACTION_MIN_INTEGER) < 0) throw new RuntimeException("Integer overflow."); return fraction.intValue(); } @Override public BigInteger bigIntValue() { return fraction.getNumerator().divide(fraction.getDenominator()); } @Override public float floatValue() { return fraction.floatValue(); } @Override public double doubleValue() { if (fraction.compareTo(BIG_FRACTION_MAX_DOUBLE) > 0 || fraction.compareTo(BIG_FRACTION_MIN_DOUBLE) < 0) throw new RuntimeException("Double overflow."); return fraction.doubleValue(); } @Override public int hashCode() { return fraction.getNumerator().hashCode() * fraction.getDenominator().hashCode(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (!(obj instanceof Number)) return false; if (obj instanceof Rational) return fraction.equals(((Rational) obj).fraction); else return ((Numeric) obj).doubleValue() == doubleValue(); } @Override public String toString() { return fraction.getNumerator().toString() + (fraction.getDenominator().equals(BigInteger.ONE) ? "" : ("/" + fraction.getDenominator().toString())); } @Override public boolean isInfinite() { return false; } @Override public boolean isNaN() { return false; } @Override public Real add(Real arg0) { checkNotNull(arg0); if (arg0 instanceof Numeric) return arg0.add(this); return createRational(fraction.add(((Rational) arg0).fraction)); } @Override public Real divide(Real arg0) { checkNotNull(arg0); if (arg0 instanceof Numeric || arg0.isZero()) return createNumeric(fraction.doubleValue() / arg0.doubleValue()); return createRational(fraction.divide(((Rational) arg0).fraction)); } @Override public Real multiply(double d) { return createNumeric(d * fraction.doubleValue()); } @Override public Rational multiply(int arg0) { return arg0 == 1 ? this : arg0 == 0 ? ZERO : new Rational(fraction.multiply(arg0)); } @Override public Real multiply(Real arg0) { checkNotNull(arg0); if (arg0 instanceof Numeric) return arg0.multiply(this); return arg0.isOne() ? this : arg0.isZero() ? ZERO : createRational(fraction.multiply(((Rational) arg0).fraction)); } public Rational multiply(Rational arg0) { checkNotNull(arg0); return arg0.isOne() ? this : arg0.isZero() ? ZERO : createRational(fraction.multiply((arg0).fraction)); } @Override public Rational negate() { return createRational(fraction.negate()); } @Override public Rational reciprocal() { return createRational(fraction.reciprocal()); } @Override public Real subtract(Real arg0) { checkNotNull(arg0); if (arg0 instanceof Numeric) return new Numeric(fraction.doubleValue() - arg0.doubleValue()); return createRational(fraction.subtract(((Rational) arg0).fraction)); } @Override public Rational subtract(BigFraction fraction) { checkNotNull(fraction); return createRational(this.fraction.subtract(fraction)); } @Override public Rational subtract(long l) { return l == 0 ? this : createRational(fraction.subtract(l)); } @Override public Rational subtract(int i) { return new Rational(fraction.subtract(i)); } @Override public Rational subtract(BigInteger bg) { NumberUtils.checkNotNull(bg); return new Rational(fraction.subtract(bg)); } public Rational reduce() { return new Rational(fraction.reduce()); } @Override public Numeric pow(double exponent) { return new Numeric(fraction.pow(exponent)); } @Override public Rational pow(BigInteger exponent) { NumberUtils.checkNotNull(exponent); return new Rational(fraction.pow(exponent)); } @Override public Rational pow(long exponent) { return new Rational(fraction.pow(exponent)); } @Override public Rational pow(int exponent) { return new Rational(fraction.pow(exponent)); } public double percentageValue() { return fraction.percentageValue(); } @Override public Rational multiply(BigFraction fraction) { NumberUtils.checkNotNull(fraction); return new Rational(fraction.multiply(fraction)); } @Override public Rational multiply(long l) { return new Rational(fraction.multiply(l)); } @Override public Rational multiply(BigInteger bg) { NumberUtils.checkNotNull(bg); return new Rational(fraction.multiply(bg)); } public long getNumeratorAsLong() { return fraction.getNumeratorAsLong(); } public int getNumeratorAsInt() { return fraction.getNumeratorAsInt(); } public BigInteger getNumerator() { return fraction.getNumerator(); } public long getDenominatorAsLong() { return fraction.getDenominatorAsLong(); } public int getDenominatorAsInt() { return fraction.getDenominatorAsInt(); } public BigInteger getDenominator() { return fraction.getDenominator(); } @Override public Rational divide(BigFraction fraction) { NumberUtils.checkNotNull(fraction); return new Rational(fraction.divide(fraction)); } @Override public Rational divide(long l) { return new Rational(fraction.divide(l)); } @Override public Rational divide(int i) { return new Rational(fraction.divide(i)); } @Override public Rational divide(BigInteger bg) { NumberUtils.checkNotNull(bg); return new Rational(fraction.divide(bg)); } @Override public Real divide(double d) { return new Numeric(fraction.doubleValue() / d); } @Override public Rational add(BigFraction fraction) { NumberUtils.checkNotNull(fraction); return new Rational(fraction.add(fraction)); } @Override public Rational add(long l) { return new Rational(fraction.add(l)); } @Override public Rational add(BigInteger bg) { NumberUtils.checkNotNull(bg); return new Rational(fraction.add(bg)); } @Override public Real add(double d) { return new Numeric(d + doubleValue()); } @Override public Rational add(int i) { return new Rational(fraction.add(i)); } @Override public Real subtract(double d) { return new Numeric(this.doubleValue() - d); } @Override public Rational abs() { return new Rational(fraction.abs()); } @Override public Numeric getNumericValue() { return new Numeric(doubleValue()); } @Override public int compareTo(Real o) { NumberUtils.checkNotNull(o); if (o instanceof Numeric) return Double.compare(doubleValue(), o.doubleValue()); return fraction.compareTo(((Rational) o).fraction); } @Override public boolean isNumeric() { return false; } @Override public boolean isZero() { //Here we do not use fraction.equals() because it has low performence return fraction.getNumerator().equals(BigInteger.ZERO);//.equals(BigFraction.ZERO); } @Override public boolean isOne() { //Here we do not use fraction.equals() because it has low performence return fraction.getNumerator().equals(BigInteger.ONE) && fraction.getDenominator().equals(BigInteger.ONE);//equals(BigFraction.ONE); } /* * Chached instenance for comparing with it (for performance) */ private static final BigInteger BI_MINUS_ONE = new BigInteger("-1"); @Override public boolean isMinusOne() { //Here we do not use fraction.equals() because it has low performence return fraction.getNumerator().equals(BI_MINUS_ONE) && fraction.getDenominator().equals(BigInteger.ONE);//equals(BigFraction.ONE); } @Override public int signum() { return fraction.getNumerator().signum(); } @Override public boolean isInteger() { return fraction.getDenominator().compareTo(BigInteger.ONE) == 0; } @Override public boolean isNatural() { return fraction.getNumerator().signum() >= 0 && isInteger(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy