001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.math3.util;
018
019
020import java.io.Serializable;
021import java.math.BigDecimal;
022import java.math.BigInteger;
023import java.math.MathContext;
024import java.math.RoundingMode;
025
026import org.apache.commons.math3.Field;
027import org.apache.commons.math3.FieldElement;
028import org.apache.commons.math3.exception.MathArithmeticException;
029import org.apache.commons.math3.exception.util.LocalizedFormats;
030
031/**
032 * Arbitrary precision decimal number.
033 * <p>
034 * This class is a simple wrapper around the standard <code>BigDecimal</code>
035 * in order to implement the {@link FieldElement} interface.
036 * </p>
037 * @since 2.0
038 * @version $Id: BigReal.java 1505938 2013-07-23 08:50:10Z luc $
039 */
040public class BigReal implements FieldElement<BigReal>, Comparable<BigReal>, Serializable {
041
042    /** A big real representing 0. */
043    public static final BigReal ZERO = new BigReal(BigDecimal.ZERO);
044
045    /** A big real representing 1. */
046    public static final BigReal ONE = new BigReal(BigDecimal.ONE);
047
048    /** Serializable version identifier. */
049    private static final long serialVersionUID = 4984534880991310382L;
050
051    /** Underlying BigDecimal. */
052    private final BigDecimal d;
053
054    /** Rounding mode for divisions. **/
055    private RoundingMode roundingMode = RoundingMode.HALF_UP;
056
057    /*** BigDecimal scale ***/
058    private int scale = 64;
059
060    /** Build an instance from a BigDecimal.
061     * @param val value of the instance
062     */
063    public BigReal(BigDecimal val) {
064        d =  val;
065    }
066
067    /** Build an instance from a BigInteger.
068     * @param val value of the instance
069     */
070    public BigReal(BigInteger val) {
071        d = new BigDecimal(val);
072    }
073
074    /** Build an instance from an unscaled BigInteger.
075     * @param unscaledVal unscaled value
076     * @param scale scale to use
077     */
078    public BigReal(BigInteger unscaledVal, int scale) {
079        d = new BigDecimal(unscaledVal, scale);
080    }
081
082    /** Build an instance from an unscaled BigInteger.
083     * @param unscaledVal unscaled value
084     * @param scale scale to use
085     * @param mc to used
086     */
087    public BigReal(BigInteger unscaledVal, int scale, MathContext mc) {
088        d = new BigDecimal(unscaledVal, scale, mc);
089    }
090
091    /** Build an instance from a BigInteger.
092     * @param val value of the instance
093     * @param mc context to use
094     */
095    public BigReal(BigInteger val, MathContext mc) {
096        d = new BigDecimal(val, mc);
097    }
098
099    /** Build an instance from a characters representation.
100     * @param in character representation of the value
101     */
102    public BigReal(char[] in) {
103        d = new BigDecimal(in);
104    }
105
106    /** Build an instance from a characters representation.
107     * @param in character representation of the value
108     * @param offset offset of the first character to analyze
109     * @param len length of the array slice to analyze
110     */
111    public BigReal(char[] in, int offset, int len) {
112        d = new BigDecimal(in, offset, len);
113    }
114
115    /** Build an instance from a characters representation.
116     * @param in character representation of the value
117     * @param offset offset of the first character to analyze
118     * @param len length of the array slice to analyze
119     * @param mc context to use
120     */
121    public BigReal(char[] in, int offset, int len, MathContext mc) {
122        d = new BigDecimal(in, offset, len, mc);
123    }
124
125    /** Build an instance from a characters representation.
126     * @param in character representation of the value
127     * @param mc context to use
128     */
129    public BigReal(char[] in, MathContext mc) {
130        d = new BigDecimal(in, mc);
131    }
132
133    /** Build an instance from a double.
134     * @param val value of the instance
135     */
136    public BigReal(double val) {
137        d = new BigDecimal(val);
138    }
139
140    /** Build an instance from a double.
141     * @param val value of the instance
142     * @param mc context to use
143     */
144    public BigReal(double val, MathContext mc) {
145        d = new BigDecimal(val, mc);
146    }
147
148    /** Build an instance from an int.
149     * @param val value of the instance
150     */
151    public BigReal(int val) {
152        d = new BigDecimal(val);
153    }
154
155    /** Build an instance from an int.
156     * @param val value of the instance
157     * @param mc context to use
158     */
159    public BigReal(int val, MathContext mc) {
160        d = new BigDecimal(val, mc);
161    }
162
163    /** Build an instance from a long.
164     * @param val value of the instance
165     */
166    public BigReal(long val) {
167        d = new BigDecimal(val);
168    }
169
170    /** Build an instance from a long.
171     * @param val value of the instance
172     * @param mc context to use
173     */
174    public BigReal(long val, MathContext mc) {
175        d = new BigDecimal(val, mc);
176    }
177
178    /** Build an instance from a String representation.
179     * @param val character representation of the value
180     */
181    public BigReal(String val) {
182        d = new BigDecimal(val);
183    }
184
185    /** Build an instance from a String representation.
186     * @param val character representation of the value
187     * @param mc context to use
188     */
189    public BigReal(String val, MathContext mc)  {
190        d = new BigDecimal(val, mc);
191    }
192
193    /***
194     * Gets the rounding mode for division operations
195     * The default is {@code RoundingMode.HALF_UP}
196     * @return the rounding mode.
197     * @since 2.1
198     */
199    public RoundingMode getRoundingMode() {
200        return roundingMode;
201    }
202
203    /***
204     * Sets the rounding mode for decimal divisions.
205     * @param roundingMode rounding mode for decimal divisions
206     * @since 2.1
207     */
208    public void setRoundingMode(RoundingMode roundingMode) {
209        this.roundingMode = roundingMode;
210    }
211
212    /***
213     * Sets the scale for division operations.
214     * The default is 64
215     * @return the scale
216     * @since 2.1
217     */
218    public int getScale() {
219        return scale;
220    }
221
222    /***
223     * Sets the scale for division operations.
224     * @param scale scale for division operations
225     * @since 2.1
226     */
227    public void setScale(int scale) {
228        this.scale = scale;
229    }
230
231    /** {@inheritDoc} */
232    public BigReal add(BigReal a) {
233        return new BigReal(d.add(a.d));
234    }
235
236    /** {@inheritDoc} */
237    public BigReal subtract(BigReal a) {
238        return new BigReal(d.subtract(a.d));
239    }
240
241    /** {@inheritDoc} */
242    public BigReal negate() {
243        return new BigReal(d.negate());
244    }
245
246    /**
247     * {@inheritDoc}
248     *
249     * @throws MathArithmeticException if {@code a} is zero
250     */
251    public BigReal divide(BigReal a) throws MathArithmeticException {
252        try {
253            return new BigReal(d.divide(a.d, scale, roundingMode));
254        } catch (ArithmeticException e) {
255            // Division by zero has occurred
256            throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED);
257        }
258    }
259
260    /**
261     * {@inheritDoc}
262     *
263     * @throws MathArithmeticException if {@code this} is zero
264     */
265    public BigReal reciprocal() throws MathArithmeticException {
266        try {
267            return new BigReal(BigDecimal.ONE.divide(d, scale, roundingMode));
268        } catch (ArithmeticException e) {
269            // Division by zero has occurred
270            throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED);
271        }
272    }
273
274    /** {@inheritDoc} */
275    public BigReal multiply(BigReal a) {
276        return new BigReal(d.multiply(a.d));
277    }
278
279    /** {@inheritDoc} */
280    public BigReal multiply(final int n) {
281        return new BigReal(d.multiply(new BigDecimal(n)));
282    }
283
284    /** {@inheritDoc} */
285    public int compareTo(BigReal a) {
286        return d.compareTo(a.d);
287    }
288
289    /** Get the double value corresponding to the instance.
290     * @return double value corresponding to the instance
291     */
292    public double doubleValue() {
293        return d.doubleValue();
294    }
295
296    /** Get the BigDecimal value corresponding to the instance.
297     * @return BigDecimal value corresponding to the instance
298     */
299    public BigDecimal bigDecimalValue() {
300        return d;
301    }
302
303    /** {@inheritDoc} */
304    @Override
305    public boolean equals(Object other) {
306        if (this == other){
307            return true;
308        }
309
310        if (other instanceof BigReal){
311            return d.equals(((BigReal) other).d);
312        }
313        return false;
314    }
315
316    /** {@inheritDoc} */
317    @Override
318    public int hashCode() {
319        return d.hashCode();
320    }
321
322    /** {@inheritDoc} */
323    public Field<BigReal> getField() {
324        return BigRealField.getInstance();
325    }
326}