Java tutorial
/* * Redberry: symbolic tensor computations. * * Copyright (c) 2010-2013: * Stanislav Poslavsky <stvlpos@mail.ru> * Bolotin Dmitriy <bolotin.dmitriy@gmail.com> * * 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 <http://www.gnu.org/licenses/>. */ package cc.redberry.core.number; import org.apache.commons.math3.exception.NullArgumentException; import org.apache.commons.math3.fraction.BigFraction; import java.io.Serializable; import java.math.BigInteger; import static cc.redberry.core.number.NumberUtils.checkNotNull; import static cc.redberry.core.number.NumberUtils.createNumeric; /** * Implementation of floating point numbers based on Java {@code double}. * <p/> * <p>This class implements all mathematical operations declared in * {@link cc.redberry.core.number.Number} as operations with doubles. So all * methods return numeric numbers. As for example, 1.0 + 2 / 3 will give * 1.666666 and so on. All mathematical methods works with its arguments using * {@link Number#doubleValue() } method. * * @author Dmitry Bolotin * @author Stanislav Poslavsky * @see Number * @see Double */ public final class Numeric extends Real implements Serializable { /** * A constant holding 0 value. */ public static final Numeric ZERO = new Numeric(0); /** * A constant holding 1 value. */ public static final Numeric ONE = new Numeric(1); /** * A constant holding -1 value. */ public static final Numeric MINUS_ONE = new Numeric(-1); /** * A constant holding the positive infinity of type * {@code double}. It is equal to the value returned by * {@code Double.longBitsToDouble(0x7ff0000000000000L)}. * * @see Double#POSITIVE_INFINITY */ public static final Numeric POSITIVE_INFINITY = new Numeric(Double.POSITIVE_INFINITY); /** * A constant holding the negative infinity of type * {@code double}. It is equal to the value returned by * {@code Double.longBitsToDouble(0xfff0000000000000L)}. * * @see Double#NEGATIVE_INFINITY */ public static final Numeric NEGATIVE_INFINITY = new Numeric(Double.NEGATIVE_INFINITY); /** * A constant holding a Not-a-Number (NaN) value of type * {@code double}. It is equivalent to the value returned by * {@code Double.longBitsToDouble(0x7ff8000000000000L)}. * * @see Double#NaN */ public static final Numeric NaN = new Numeric(Double.NaN); /** * A constant holding the largest positive finite value of type * {@code double}, (2-2<sup>-52</sup>)·2<sup>1023</sup>. It is equal * to the hexadecimal floating-point literal * {@code 0x1.fffffffffffffP+1023} and also equal to * {@code Double.longBitsToDouble(0x7fefffffffffffffL)}. * * @see Double#MAX_VALUE */ public static final Numeric MAX_VALUE = new Numeric(Double.MAX_VALUE); /** * A constant holding the smallest positive normal value of type * {@code double}, 2<sup>-1022</sup>. It is equal to the hexadecimal * floating-point literal {@code 0x1.0p-1022} and also equal to {@code Double.longBitsToDouble(0x0010000000000000L)}. * * @see Double#MIN_NORMAL */ public static final Numeric MIN_NORMAL = new Numeric(Double.MIN_NORMAL); // 2.2250738585072014E-308 /** * A constant holding the smallest positive nonzero value of type * {@code double}, 2<sup>-1074</sup>. It is equal to the hexadecimal * floating-point literal * {@code 0x0.0000000000001P-1022} and also equal to * {@code Double.longBitsToDouble(0x1L)}. * * @see Double#MIN_VALUE */ public static final Numeric MIN_VALUE = new Numeric(Double.MIN_VALUE); // 4.9e-324 /* * numeric value */ private final double value; public Numeric(final double value) { this.value = value; } public Numeric(final int value) { this.value = value; } public Numeric(final float value) { this.value = value; } /** * Constructs a new {@code Numeric} instance, which {@code double} variable * is taken from {@code value.doubleValue()}. So, this constructor makes <br>{@code * this.value = value.doubleValue(); * } * * @param value the value, which double representation to be represented by * the {@code Double}. * @throws NullArgumentException if value is {@code null}. */ public Numeric(final Number value) { checkNotNull(value); this.value = value.doubleValue(); } @Override public double doubleValue() { return value; } @Override public float floatValue() { return (float) value; } @Override public int intValue() { return (int) value; } @Override public long longValue() { return (long) value; } @Override public Numeric add(final Real n) { checkNotNull(n); return add(n.doubleValue()); } @Override public Numeric divide(final Real n) { checkNotNull(n); return divide(n.doubleValue()); } @Override public Numeric multiply(final int n) { return n == 1 ? this : createNumeric(value * n); } @Override public Numeric multiply(final Real n) { checkNotNull(n); return multiply(n.doubleValue()); } @Override public Numeric subtract(final Real n) { checkNotNull(n); return subtract(n.doubleValue()); } @Override public Numeric negate() { return createNumeric(-value); } @Override public Numeric reciprocal() { return createNumeric(1 / value); } /** * @return similar to {@link Double} * @see Double#hashCode() */ @Override public int hashCode() { long bits = Double.doubleToLongBits(value * value); return (int) (bits ^ (bits >>> 32)); } /** * @return {@code Double.isInfinite(value)} * @see Double#isInfinite(double) */ @Override public boolean isInfinite() { return Double.isInfinite(value); } /** * @return {@code Double.isNaN(value)} * @see Double#isNaN(double) */ @Override public boolean isNaN() { return Double.isNaN(value); } @Override public Numeric abs() { return value >= 0 ? this : negate(); } @Override public Numeric add(double d) { return d == 0 ? this : createNumeric(value + d); } @Override public Numeric add(int i) { return add((double) i); } @Override public Numeric add(BigFraction fraction) { checkNotNull(fraction); //FUTURE fraction.doubleValue() is very unefficient operation return add(fraction.doubleValue()); } @Override public Numeric add(long l) { return add((double) l); } @Override public Numeric add(BigInteger bg) { checkNotNull(bg); //FUTURE fraction.doubleValue() is very unefficient operation return add(bg.doubleValue()); } @Override public Numeric divide(double d) { return d == 1 ? this : createNumeric(value / d); } @Override public Numeric divide(BigFraction fraction) { checkNotNull(fraction); //FUTURE fraction.doubleValue() is very unefficient operation return divide(fraction.doubleValue()); } @Override public Numeric divide(long l) { return divide((double) l); } @Override public Numeric divide(int i) { return divide((double) i); } @Override public Numeric divide(BigInteger bg) { checkNotNull(bg); //FUTURE fraction.doubleValue() is very unefficient operation return divide(bg.doubleValue()); } @Override public Numeric multiply(double d) { return d == 1.0 ? this : createNumeric(d * value); } @Override public Numeric multiply(BigFraction fraction) { checkNotNull(fraction); //FUTURE fraction.doubleValue() is very unefficient operation return multiply(fraction.doubleValue()); } @Override public Numeric multiply(long l) { return multiply((double) l); } @Override public Numeric multiply(BigInteger bg) { checkNotNull(bg); //FUTURE bg.doubleValue() is very unefficient operation return multiply(bg.doubleValue()); } @Override public Numeric subtract(BigFraction fraction) { return add(fraction.negate()); } @Override public Numeric subtract(long l) { return add((double) (-l)); } @Override public Numeric subtract(int i) { return add((double) (-i)); } @Override public Numeric subtract(BigInteger bg) { return add(bg.negate()); } @Override public Numeric subtract(double d) { return add(-d); } @Override public Numeric pow(double exponent) { return createNumeric(StrictMath.pow(value, exponent)); } @Override public Numeric pow(BigInteger exponent) { checkNotNull(exponent); //FUTURE bg.doubleValue() is very unefficient operation return pow(exponent.doubleValue()); } @Override public Numeric pow(long exponent) { return pow((double) exponent); } @Override public Numeric pow(int exponent) { return pow((double) exponent); } /** * @see Double#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null) return false; if (!(obj instanceof Number)) return false; return Double.doubleToLongBits(value) == Double.doubleToLongBits(((Number) obj).doubleValue()); } /** * @see Double#toString() */ @Override public String toString() { return Double.toString(value); } /** * @return this */ @Override public Numeric getNumericValue() { return this; } @Override public boolean isZero() { return value == 0.0; } /** * @see Double#compare(double, double) */ @Override public int compareTo(Real o) { checkNotNull(o); return Double.compare(value, o.doubleValue()); } @Override public boolean isNumeric() { return true; } @Override public boolean isOne() { return value == 1.0; } @Override public boolean isMinusOne() { return value == -1.0; } @Override public int signum() { return value > 0 ? 1 : value == 0 ? 0 : -1; } @Override public boolean isInteger() { return false; } @Override public boolean isNatural() { return false; } }