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.math4.legacy.linear;
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.math4.legacy.core.Field;
027import org.apache.commons.math4.legacy.core.FieldElement;
028import org.apache.commons.math4.legacy.exception.MathArithmeticException;
029import org.apache.commons.math4.legacy.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 */
039public class BigReal implements FieldElement<BigReal>, Comparable<BigReal>, Serializable {
040
041    /** A big real representing 0. */
042    public static final BigReal ZERO = new BigReal(BigDecimal.ZERO);
043
044    /** A big real representing 1. */
045    public static final BigReal ONE = new BigReal(BigDecimal.ONE);
046
047    /** Serializable version identifier. */
048    private static final long serialVersionUID = 4984534880991310382L;
049
050    /** Underlying BigDecimal. */
051    private final BigDecimal d;
052
053    /** Rounding mode for divisions. */
054    private RoundingMode roundingMode = RoundingMode.HALF_UP;
055
056    /** BigDecimal scale. */
057    private int scale = 64;
058
059    /** Build an instance from a BigDecimal.
060     * @param val value of the instance
061     */
062    public BigReal(BigDecimal val) {
063        d =  val;
064    }
065
066    /** Build an instance from a BigInteger.
067     * @param val value of the instance
068     */
069    public BigReal(BigInteger val) {
070        d = new BigDecimal(val);
071    }
072
073    /** Build an instance from an unscaled BigInteger.
074     * @param unscaledVal unscaled value
075     * @param scale scale to use
076     */
077    public BigReal(BigInteger unscaledVal, int scale) {
078        d = new BigDecimal(unscaledVal, scale);
079    }
080
081    /** Build an instance from an unscaled BigInteger.
082     * @param unscaledVal unscaled value
083     * @param scale scale to use
084     * @param mc to used
085     */
086    public BigReal(BigInteger unscaledVal, int scale, MathContext mc) {
087        d = new BigDecimal(unscaledVal, scale, mc);
088    }
089
090    /** Build an instance from a BigInteger.
091     * @param val value of the instance
092     * @param mc context to use
093     */
094    public BigReal(BigInteger val, MathContext mc) {
095        d = new BigDecimal(val, mc);
096    }
097
098    /** Build an instance from a characters representation.
099     * @param in character representation of the value
100     */
101    public BigReal(char[] in) {
102        d = new BigDecimal(in);
103    }
104
105    /** Build an instance from a characters representation.
106     * @param in character representation of the value
107     * @param offset offset of the first character to analyze
108     * @param len length of the array slice to analyze
109     */
110    public BigReal(char[] in, int offset, int len) {
111        d = new BigDecimal(in, offset, len);
112    }
113
114    /** Build an instance from a characters representation.
115     * @param in character representation of the value
116     * @param offset offset of the first character to analyze
117     * @param len length of the array slice to analyze
118     * @param mc context to use
119     */
120    public BigReal(char[] in, int offset, int len, MathContext mc) {
121        d = new BigDecimal(in, offset, len, mc);
122    }
123
124    /** Build an instance from a characters representation.
125     * @param in character representation of the value
126     * @param mc context to use
127     */
128    public BigReal(char[] in, MathContext mc) {
129        d = new BigDecimal(in, mc);
130    }
131
132    /** Build an instance from a double.
133     * @param val value of the instance
134     */
135    public BigReal(double val) {
136        d = new BigDecimal(val);
137    }
138
139    /** Build an instance from a double.
140     * @param val value of the instance
141     * @param mc context to use
142     */
143    public BigReal(double val, MathContext mc) {
144        d = new BigDecimal(val, mc);
145    }
146
147    /** Build an instance from an int.
148     * @param val value of the instance
149     */
150    public BigReal(int val) {
151        d = new BigDecimal(val);
152    }
153
154    /** Build an instance from an int.
155     * @param val value of the instance
156     * @param mc context to use
157     */
158    public BigReal(int val, MathContext mc) {
159        d = new BigDecimal(val, mc);
160    }
161
162    /** Build an instance from a long.
163     * @param val value of the instance
164     */
165    public BigReal(long val) {
166        d = new BigDecimal(val);
167    }
168
169    /** Build an instance from a long.
170     * @param val value of the instance
171     * @param mc context to use
172     */
173    public BigReal(long val, MathContext mc) {
174        d = new BigDecimal(val, mc);
175    }
176
177    /** Build an instance from a String representation.
178     * @param val character representation of the value
179     */
180    public BigReal(String val) {
181        d = new BigDecimal(val);
182    }
183
184    /** Build an instance from a String representation.
185     * @param val character representation of the value
186     * @param mc context to use
187     */
188    public BigReal(String val, MathContext mc)  {
189        d = new BigDecimal(val, mc);
190    }
191
192    /***
193     * Gets the rounding mode for division operations.
194     * The default is {@code RoundingMode.HALF_UP}
195     * @return the rounding mode.
196     * @since 2.1
197     */
198    public RoundingMode getRoundingMode() {
199        return roundingMode;
200    }
201
202    /***
203     * Sets the rounding mode for decimal divisions.
204     * @param roundingMode rounding mode for decimal divisions
205     * @since 2.1
206     */
207    public void setRoundingMode(RoundingMode roundingMode) {
208        this.roundingMode = roundingMode;
209    }
210
211    /***
212     * Sets the scale for division operations.
213     * The default is 64
214     * @return the scale
215     * @since 2.1
216     */
217    public int getScale() {
218        return scale;
219    }
220
221    /***
222     * Sets the scale for division operations.
223     * @param scale scale for division operations
224     * @since 2.1
225     */
226    public void setScale(int scale) {
227        this.scale = scale;
228    }
229
230    /** {@inheritDoc} */
231    @Override
232    public BigReal add(BigReal a) {
233        return new BigReal(d.add(a.d));
234    }
235
236    /** {@inheritDoc} */
237    @Override
238    public BigReal subtract(BigReal a) {
239        return new BigReal(d.subtract(a.d));
240    }
241
242    /** {@inheritDoc} */
243    @Override
244    public BigReal negate() {
245        return new BigReal(d.negate());
246    }
247
248    /**
249     * {@inheritDoc}
250     *
251     * @throws MathArithmeticException if {@code a} is zero
252     */
253    @Override
254    public BigReal divide(BigReal a) throws MathArithmeticException {
255        try {
256            return new BigReal(d.divide(a.d, scale, roundingMode));
257        } catch (ArithmeticException e) {
258            // Division by zero has occurred
259            throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED);
260        }
261    }
262
263    /**
264     * {@inheritDoc}
265     *
266     * @throws MathArithmeticException if {@code this} is zero
267     */
268    @Override
269    public BigReal reciprocal() throws MathArithmeticException {
270        try {
271            return new BigReal(BigDecimal.ONE.divide(d, scale, roundingMode));
272        } catch (ArithmeticException e) {
273            // Division by zero has occurred
274            throw new MathArithmeticException(LocalizedFormats.ZERO_NOT_ALLOWED);
275        }
276    }
277
278    /** {@inheritDoc} */
279    @Override
280    public BigReal multiply(BigReal a) {
281        return new BigReal(d.multiply(a.d));
282    }
283
284    /** {@inheritDoc} */
285    @Override
286    public BigReal multiply(final int n) {
287        return new BigReal(d.multiply(new BigDecimal(n)));
288    }
289
290    /** {@inheritDoc} */
291    @Override
292    public int compareTo(BigReal a) {
293        return d.compareTo(a.d);
294    }
295
296    /** Get the double value corresponding to the instance.
297     * @return double value corresponding to the instance
298     */
299    public double doubleValue() {
300        return d.doubleValue();
301    }
302
303    /** Get the BigDecimal value corresponding to the instance.
304     * @return BigDecimal value corresponding to the instance
305     */
306    public BigDecimal bigDecimalValue() {
307        return d;
308    }
309
310    /** {@inheritDoc} */
311    @Override
312    public boolean equals(Object other) {
313        if (this == other){
314            return true;
315        }
316
317        if (other instanceof BigReal) {
318            return d.compareTo(((BigReal) other).d) == 0;
319        }
320        return false;
321    }
322
323    /** {@inheritDoc} */
324    @Override
325    public int hashCode() {
326        return Double.hashCode(d.doubleValue());
327    }
328
329    /** {@inheritDoc} */
330    @Override
331    public Field<BigReal> getField() {
332        return BigRealField.getInstance();
333    }
334}