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

edu.jas.arith.BigDecimal Maven / Gradle / Ivy

The newest version!
/*
 * $Id: BigDecimal.java 4315 2012-12-15 19:23:25Z kredel $
 */

package edu.jas.arith;


import java.io.Reader;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import edu.jas.kern.StringUtil;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.RingFactory;


/**
 * BigDecimal class to make java.math.BigDecimal available with RingElem
 * interface. Objects of this class are immutable. Experimental, use with care,
 * compareTo is hacked.
 * @author Heinz Kredel
 * @see java.math.BigDecimal
 */

public final class BigDecimal implements GcdRingElem, RingFactory {


    /**
     * The data structure.
     */
    public final java.math.BigDecimal val;


    private final static Random random = new Random();


    //public static final int DEFAULT_PRECISION = 50;
    //public static final MathContext DEFAULT_CONTEXT = new MathContext(DEFAULT_PRECISION);

    public static final MathContext DEFAULT_CONTEXT = MathContext.DECIMAL128;
    public static final int DEFAULT_PRECISION = DEFAULT_CONTEXT.getPrecision();


    public final MathContext context;


    /**
     * The constant 0.
     */
    public final static BigDecimal ZERO = new BigDecimal(java.math.BigDecimal.ZERO);


    /**
     * The constant 1.
     */
    public final static BigDecimal ONE = new BigDecimal(java.math.BigDecimal.ONE);


    /**
     * Constructor for BigDecimal from math.BigDecimal.
     * @param a java.math.BigDecimal.
     */
    public BigDecimal(java.math.BigDecimal a) {
        this(a, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from math.BigDecimal.
     * @param a java.math.BigDecimal.
     * @param mc MathContext.
     */
    public BigDecimal(java.math.BigDecimal a, MathContext mc) {
        val = a;
        context = mc;
    }


    /**
     * Constructor for BigDecimal from long.
     * @param a long.
     */
    public BigDecimal(long a) {
        this(a, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from long and a context.
     * @param a long.
     * @param mc MathContext.
     */
    public BigDecimal(long a, MathContext mc) {
        this(new java.math.BigDecimal(String.valueOf(a)), mc);
    }


    /**
     * Constructor for BigDecimal from double.
     * @param a double.
     */
    public BigDecimal(double a) {
        this(a, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from double and a context.
     * @param a double.
     * @param mc MathContext.
     */
    public BigDecimal(double a, MathContext mc) {
        this(new java.math.BigDecimal(a), mc);
    }


    /**
     * Constructor for BigDecimal from java.math.BigInteger.
     * @param a java.math.BigInteger.
     */
    public BigDecimal(java.math.BigInteger a) {
        this(a, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from java.math.BigInteger.
     * @param a java.math.BigInteger.
     * @param mc MathContext.
     */
    public BigDecimal(java.math.BigInteger a, MathContext mc) {
        this(new java.math.BigDecimal(a), mc);
    }


    /**
     * Constructor for BigDecimal from BigRational.
     * @param a edu.jas.arith.BigRational.
     */
    public BigDecimal(BigRational a) {
        this(a, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from BigRational.
     * @param a edu.jas.arith.BigRational.
     * @param mc MathContext.
     */
    public BigDecimal(BigRational a, MathContext mc) {
        this((new java.math.BigDecimal(a.num,mc)).divide(new java.math.BigDecimal(a.den,mc), mc), mc);
    }


    /**
     * Constructor for BigDecimal from String.
     * @param s String.
     */
    public BigDecimal(String s) {
        this(s, DEFAULT_CONTEXT);
    }


    /**
     * Constructor for BigDecimal from String.
     * @param s String.
     * @param mc MathContext.
     */
    public BigDecimal(String s, MathContext mc) {
        this(new java.math.BigDecimal(s.trim()), mc);
    }


    /**
     * Constructor for BigDecimal without parameters.
     */
    public BigDecimal() {
        this(java.math.BigDecimal.ZERO, DEFAULT_CONTEXT);
    }


    /**
     * Get the value.
     * @return val java.math.BigDecimal. public java.math.BigDecimal getVal() {
     *         return val; }
     */


    /**
     * Get the corresponding element factory.
     * @return factory for this Element.
     * @see edu.jas.structure.Element#factory()
     */
    public BigDecimal factory() {
        return this;
    }


    /**
     * Get a list of the generating elements.
     * @return list of generators for the algebraic structure.
     * @see edu.jas.structure.ElemFactory#generators()
     */
    public List generators() {
        List g = new ArrayList(1);
        g.add(getONE());
        return g;
    }


    /**
     * Is this structure finite or infinite.
     * @return true if this structure is finite, else false.
     * @see edu.jas.structure.ElemFactory#isFinite() Note:  is actually
     *      finite but returns false.
     */
    public boolean isFinite() {
        return false;
    }


    /**
     * Clone this.
     * @see java.lang.Object#clone()
     */
    @Override
    public BigDecimal copy() {
        return new BigDecimal(val, context);
    }


    /**
     * Copy BigDecimal element c.
     * @param c BigDecimal.
     * @return a copy of c.
     */
    public BigDecimal copy(BigDecimal c) {
        return new BigDecimal(c.val, c.context);
    }


    /**
     * Get the zero element.
     * @return 0.
     */
    public BigDecimal getZERO() {
        return ZERO;
    }


    /**
     * Get the one element.
     * @return 1.
     */
    public BigDecimal getONE() {
        return ONE;
    }


    /**
     * Query if this ring is commutative.
     * @return true.
     */
    public boolean isCommutative() {
        return true;
    }


    /**
     * Query if this ring is associative. Floating point number addition is not
     * associative, but multiplication is.
     * @return true.
     */
    public boolean isAssociative() {
        return true;
    }


    /**
     * Query if this ring is a field.
     * @return true.
     */
    public boolean isField() {
        return true;
    }


    /**
     * Characteristic of this ring.
     * @return characteristic of this ring.
     */
    public java.math.BigInteger characteristic() {
        return java.math.BigInteger.ZERO;
    }


    /**
     * Get a BigDecimal element from a math.BigDecimal.
     * @param a math.BigDecimal.
     * @return a as BigDecimal.
     */
    public BigDecimal fromInteger(java.math.BigInteger a) {
        return new BigDecimal(new java.math.BigDecimal(a), context);
    }


    /**
     * Get a BigDecimal element from a math.BigDecimal.
     * @param a math.BigDecimal.
     * @return a as BigDecimal.
     */
    public static BigDecimal valueOf(java.math.BigDecimal a) {
        return new BigDecimal(a, DEFAULT_CONTEXT);
    }


    /**
     * Get a BigDecimal element from long.
     * @param a long.
     * @return a as BigDecimal.
     */
    public BigDecimal fromInteger(long a) {
        return new BigDecimal(a, context);
    }


    /**
     * Get a BigDecimal element from long.
     * @param a long.
     * @return a as BigDecimal.
     */
    public static BigDecimal valueOf(long a) {
        return new BigDecimal(a, DEFAULT_CONTEXT);
    }


    /**
     * Is BigDecimal number zero.
     * @return If this is 0 then true is returned, else false.
     * @see edu.jas.structure.RingElem#isZERO()
     */
    public boolean isZERO() {
        return val.compareTo(java.math.BigDecimal.ZERO) == 0;
    }


    /**
     * Is BigDecimal number one.
     * @see edu.jas.structure.RingElem#isONE()
     */
    public boolean isONE() {
        return val.compareTo(java.math.BigDecimal.ONE) == 0;
    }


    /**
     * Is BigDecimal number unit.
     * @see edu.jas.structure.RingElem#isUnit()
     */
    public boolean isUnit() {
        return (!isZERO());
    }


    /**
     * Get the String representation.
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        //return val.toString() + "(ulp=" + val.ulp() + ")";
        return val.toString();
    }


    /**
     * Get a scripting compatible string representation.
     * @return script compatible representation for this Element.
     * @see edu.jas.structure.Element#toScript()
     */
    //JAVA6only: @Override
    public String toScript() {
        // Python case
        return toString();
    }


    /**
     * Get a scripting compatible string representation of the factory.
     * @return script compatible representation for this ElemFactory.
     * @see edu.jas.structure.Element#toScriptFactory()
     */
    //JAVA6only: @Override
    public String toScriptFactory() {
        // Python case
        return "DD()";
    }


    /**
     * Compare to BigDecimal b. Experimental, is hacked.
     * @param b BigDecimal.
     * @return 0 if abs(this-b) < epsilon, 1 if this > b, -1 if this < b.
     */
    //JAVA6only: @Override
    public int compareTo(BigDecimal b) {
        //if (false) {
        //    return val.compareTo(b.val);
        //}
        java.math.BigDecimal s = val.subtract(b.val, context);
        java.math.BigDecimal u1 = val.ulp();
        java.math.BigDecimal u2 = b.val.ulp();
        int u = Math.min(u1.scale(), u2.scale());
        //System.out.println("u = " + u + ", s = " + s);
        java.math.BigDecimal eps;
        if (u <= 0) {
            eps = u1.max(u2);
        } else {
            eps = u1.min(u2);
        }
        //eps = eps.movePointRight(1);
        //System.out.println("ctx = " + context);
        //System.out.println("eps = " + eps);
        int t = s.abs().compareTo(eps);
        if (t < 1) {
            return 0;
        }
        return s.signum();
    }


    /**
     * Comparison with any other object.
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object b) {
        if (!(b instanceof BigDecimal)) {
            return false;
        }
        BigDecimal bi = (BigDecimal) b;
        return val.equals(bi.val);
    }


    /**
     * Hash code for this BigDecimal.
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return val.hashCode();
    }


    /**
     * Absolute value of this.
     * @see edu.jas.structure.RingElem#abs()
     */
    public BigDecimal abs() {
        return new BigDecimal(val.abs(), context);
    }


    /* Negative value of this.
     * @see edu.jas.structure.RingElem#negate()
     */
    public BigDecimal negate() {
        return new BigDecimal(val.negate(), context);
    }


    /**
     * signum.
     * @see edu.jas.structure.RingElem#signum()
     */
    public int signum() {
        return val.signum();
    }


    /**
     * BigDecimal subtract.
     * @param S BigDecimal.
     * @return this-S.
     */
    public BigDecimal subtract(BigDecimal S) {
        return new BigDecimal(val.subtract(S.val, context));
    }


    /**
     * BigDecimal divide.
     * @param S BigDecimal.
     * @return this/S.
     */
    public BigDecimal divide(BigDecimal S) {
        return new BigDecimal(val.divide(S.val, context));
    }


    /**
     * Integer inverse. R is a non-zero integer. S=1/R if defined else 0.
     * @see edu.jas.structure.RingElem#inverse()
     */
    public BigDecimal inverse() {
        return ONE.divide(this);
    }


    /**
     * BigDecimal remainder.
     * @param S BigDecimal.
     * @return this - (this/S)*S.
     */
    public BigDecimal remainder(BigDecimal S) {
        return new BigDecimal(val.remainder(S.val, context));
    }


    /**
     * BigDecimal compute quotient and remainder.
     * @param S BigDecimal.
     * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S).
     */
    public BigDecimal[] quotientRemainder(BigDecimal S) {
        BigDecimal[] qr = new BigDecimal[2];
        java.math.BigDecimal[] C = val.divideAndRemainder(S.val, context);
        qr[0] = new BigDecimal(C[0]);
        qr[1] = new BigDecimal(C[1]);
        return qr;
    }


    /**
     * BigDecimal compute quotient and remainder.
     * @param S BigDecimal.
     * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S).
     * @deprecated use quotientRemainder()
     */
    @Deprecated
    public BigDecimal[] divideAndRemainder(BigDecimal S) {
        return quotientRemainder(S);
    }


    /**
     * BigDecimal greatest common divisor.
     * @param S BigDecimal.
     * @return gcd(this,S).
     */
    public BigDecimal gcd(BigDecimal S) {
        throw new UnsupportedOperationException("BigDecimal.gcd() not implemented");
        //return new BigDecimal( val.gcd( S.val ) );
    }


    /**
     * BigDecimal extended greatest common divisor.
     * @param S BigDecimal.
     * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
     */
    public BigDecimal[] egcd(BigDecimal S) {
        throw new UnsupportedOperationException("BigDecimal.egcd() not implemented");
    }


    /**
     * BigDecimal random.
     * @param n such that 0 ≤ val(r) ≤ (2n-1). 0 ≤ exp(r)
     *            ≤ (100-1).
     * @return r, a random BigDecimal.
     */
    public BigDecimal random(int n) {
        return random(n, random);
    }


    /**
     * BigDecimal random.
     * @param n such that 0 ≤ val(r) ≤ (2n-1). 0 ≤ exp(r)
     *            ≤ (100-1).
     * @param rnd is a source for random bits.
     * @return r, a random BigDecimal.
     */
    public BigDecimal random(int n, Random rnd) {
        return random(n, 100, rnd);
    }


    /**
     * BigDecimal random.
     * @param n such that 0 ≤ val(r) ≤ (2n-1).
     * @param e such that 0 ≤ exp(r) ≤ (e-1).
     * @return r, a random BigDecimal.
     */
    public BigDecimal random(int n, int e) {
        return random(n, e, random);
    }


    /**
     * BigDecimal random.
     * @param n such that 0 ≤ val(r) ≤ (2n-1).
     * @param e such that 0 ≤ exp(r) ≤ (e-1).
     * @param rnd is a source for random bits.
     * @return r, a random BigDecimal.
     */
    public BigDecimal random(int n, int e, Random rnd) {
        java.math.BigInteger r = new java.math.BigInteger(n, rnd);
        if (rnd.nextBoolean()) {
            r = r.negate();
        }
        int scale = rnd.nextInt(e);
        if (rnd.nextBoolean()) {
            scale = -scale;
        }
        java.math.BigDecimal d = new java.math.BigDecimal(r, scale, context);
        return new BigDecimal(d, context);
    }


    /**
     * BigDecimal multiply.
     * @param S BigDecimal.
     * @return this*S.
     */
    public BigDecimal multiply(BigDecimal S) {
        return new BigDecimal(val.multiply(S.val, context));
    }


    /**
     * BigDecimal summation.
     * @param S BigDecimal.
     * @return this+S.
     */
    public BigDecimal sum(BigDecimal S) {
        return new BigDecimal(val.add(S.val, context));
    }


    /**
     * BigDecimal parse from String.
     * @param s String.
     * @return Biginteger from s.
     */
    public BigDecimal parse(String s) {
        return new BigDecimal(s, context);
    }


    /**
     * BigDecimal parse from Reader.
     * @param r Reader.
     * @return next Biginteger from r.
     */
    public BigDecimal parse(Reader r) {
        return parse(StringUtil.nextString(r));
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy