001/* A library of additional mathematical operations beyond those provided
002 by the Java Math class.
003
004 Copyright (c) 1998-2013 The Regents of the University of California.
005 All rights reserved.
006
007 Permission is hereby granted, without written agreement and without
008 license or royalty fees, to use, copy, modify, and distribute this
009 software and its documentation for any purpose, provided that the above
010 copyright notice and the following two paragraphs appear in all copies
011 of this software.
012
013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
017 SUCH DAMAGE.
018
019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
024 ENHANCEMENTS, OR MODIFICATIONS.
025
026 PT_COPYRIGHT_VERSION_2
027 COPYRIGHTENDKEY
028
029 */
030package ptolemy.math;
031
032///////////////////////////////////////////////////////////////////
033//// ExtendedMath
034
035/**
036 ExtendedMath is a library of additional mathematical operations
037 beyond those provided by the Java Math class.
038
039 @author Albert Chen, William Wu, Edward A. Lee, Jeff Tsay
040 @version $Id$
041 @since Ptolemy II 0.2
042 @Pt.ProposedRating Yellow (ctsay)
043 @Pt.AcceptedRating Red (cxh)
044 */
045public class ExtendedMath {
046    ///////////////////////////////////////////////////////////////////
047    ////                         public methods                    ////
048
049    /** Return the inverse hyperbolic cosine of the argument.
050     *  The argument is required to be greater than one, or an
051     *  IllegalArgumentException is thrown (this is a runtime
052     *  exception, so it need not be declared).
053     *  The returned value is positive.
054     */
055    public static final double acosh(final double x) {
056        // FIXME: Is the range of the argument correct?
057        if (x < 1) {
058            throw new IllegalArgumentException("ExtendedMath.acosh: Argument "
059                    + "is required to be greater than 1.  Got " + x);
060        }
061
062        return Math.log(x + Math.sqrt(x * x - 1));
063    }
064
065    /** Return the inverse hyperbolic sine of the argument.
066     */
067    public static final double asinh(final double x) {
068        double result;
069
070        if (x < 0) {
071            result = -Math.log(-x + Math.sqrt(x * x + 1));
072        } else {
073            result = Math.log(x + Math.sqrt(x * x + 1));
074        }
075
076        return result;
077    }
078
079    /** Return the hyperbolic cosine of the argument.
080     */
081    public static final double cosh(final double x) {
082        return (Math.exp(x) + Math.exp(-x)) / 2;
083    }
084
085    /** Implement Euclid's method for finding the Greatest Common Divisor
086     * (GCD) of
087     *  two numbers.  If the numbers are negative, then we compute the
088     *  GCD of their absolute values.
089     */
090    public static int gcd(int u, int v) {
091        int t;
092
093        if (u < 0) {
094            u = -u;
095        }
096
097        if (v < 0) {
098            v = -v;
099        }
100
101        while (u > 0) {
102            if (u < v) {
103                t = u;
104                u = v;
105                v = t;
106            } else {
107                u = u % v;
108            }
109        }
110
111        return v;
112    }
113
114    /** Return the base-10 logarithm of the argument. */
115    public static final double log10(final double x) {
116        return Math.log(x) * _ONEOVERLN10;
117    }
118
119    /** Return the base-2 logarithm of the argument. */
120    public static final double log2(final double x) {
121        return Math.log(x) * _ONEOVERLN2;
122    }
123
124    /** Compute the remainder after dividing the first argument by the
125     *  second argument as prescribed by the IEEE 754 standard.  This
126     *  is implemented by the java.lang.Math class method IEEERemainder.
127     *  The documentation for that class says:
128     *
129     *  <p> "The remainder value is mathematically equal to f1 - f2
130     *  &times; <i>n</i>, where <i>n</i> is the mathematical integer
131     *  closest to the exact mathematical value of the quotient f1/f2,
132     *  and if two mathematical integers are equally close to f1/f2,
133     *  then <i>n</i> is the integer that is even. If the remainder is
134     *  zero, its sign is the same as the sign of the first
135     *  argument. Special cases:
136     *
137     *  <ul>
138     *  <li> If either argument is NaN, or the first argument is
139     *  infinite, or the second argument is positive zero or negative
140     *  zero, then the result is NaN.
141     *  <li> If the first argument is finite
142     *  and the second argument is infinite, then the result is the
143     *  same as the first argument.
144     *  </ul>
145     */
146    public static double remainder(double f1, double f2) {
147        return Math.IEEEremainder(f1, f2);
148    }
149
150    /** Round to the nearest integer.  If the argument is NaN, then
151     *  the return value is 0. If the argument is out of range, then
152     *  the return value is Integer.MAX_VALUE or Integer.MIN_VALUE,
153     *  depending on the sign of the argument.
154     *  @param x The number to round.
155     *  @return The nearest integer.
156     */
157    public static final int roundToInt(final double x) {
158        long returnValue = Math.round(x);
159
160        if (returnValue >= Integer.MAX_VALUE) {
161            return Integer.MAX_VALUE;
162        }
163
164        if (returnValue <= Integer.MIN_VALUE) {
165            return Integer.MIN_VALUE;
166        }
167
168        return (int) returnValue;
169    }
170
171    /** If the argument is less than zero, return -1, otherwise
172     *  return 1.
173     */
174    public static final int sgn(final double x) {
175        if (x < 0) {
176            return -1;
177        } else {
178            return 1;
179        }
180    }
181
182    /** Return the hyperbolic sine of the argument.
183     */
184    public static final double sinh(final double x) {
185        return (Math.exp(x) - Math.exp(-x)) / 2;
186    }
187
188    /** Return the hyperbolic tangent of the argument.
189     */
190    public static final double tanh(final double x) {
191        return sinh(x) / cosh(x);
192    }
193
194    ///////////////////////////////////////////////////////////////////
195    ////                         public variables                  ////
196
197    /** sqrt(2). */
198    public static final double SQRT_2 = Math.sqrt(2.0);
199
200    /** 1 / sqrt(2). */
201    public static final double ONE_OVER_SQRT_2 = 1.0 / SQRT_2;
202
203    /** PI / 2. */
204    public static final double PI_OVER_2 = Math.PI * 0.5;
205
206    /** PI / 4. */
207    public static final double PI_OVER_4 = Math.PI * 0.25;
208
209    /** The smallest, normalized, positive double value with a single precision.
210     */
211    public static final double SINGLE_PRECISION_SMALLEST_NORMALIZED_POSITIVE_DOUBLE = Math
212            .pow(2.0, -126);
213
214    /** The smallest, normalized, positive double value with a double precision.
215     */
216    public static final double DOUBLE_PRECISION_SMALLEST_NORMALIZED_POSITIVE_DOUBLE = Math
217            .pow(2.0, -1022);
218
219    /** The constant value of a double representation that has all bits as
220     *  1 except the sign bit, where only the significand contributes to the
221     *  value. This value is equal to 1 + 1/2 + 1/2^2 + 1/2^3 + ... + 1/2^m,
222     *  where m is the number of bits for the significand. M is 52 for
223     *  a double precision floating point number.
224     */
225    public static final double DOUBLE_PRECISION_SIGNIFICAND_ONLY = 2.0
226            - Math.pow(2.0, -52);
227
228    /** The constant value of a double representation that has all bits as
229     *  1 except the sign bit, where only the significand contributes to the
230     *  value. This value is equal to 1 + 1/2 + 1/2^2 + 1/2^3 + ... + 1/2^m,
231     *  where m is the number of bits for the significand. M is 23 for
232     *  a single precision floating point number.
233     */
234    public static final double SINGLE_PRECISION_SIGNIFICAND_ONLY = 2.0
235            - Math.pow(2.0, -23);
236
237    ///////////////////////////////////////////////////////////////////
238    ////                         private variables                 ////
239    private static final double _ONEOVERLN2 = 1.0 / Math.log(2.0);
240
241    private static final double _ONEOVERLN10 = 1.0 / Math.log(10.0);
242}