Java tutorial
//package org.j4me.util; /** * Implements the methods which are in the standard J2SE's <code>Math</code> class, * but are not in in J2ME's. * <p> * The following methods are still missing from the implementation: * <ul> * <li><code>public static double exp (double a)</code> * <li><code>public static double log (double a)</code> * <li><code>public static double pow (double a, double b)</code> * <li><code>public static double random ()</code> * <li><code>public static double rint()</code> * </ul> * * @see java.lang.Math */ public final class MathFunc { /** * Constant for PI divided by 2. */ private static final double PIover2 = Math.PI / 2; /** * Constant for PI divided by 4. */ private static final double PIover4 = Math.PI / 4; /** * Constant for PI divided by 6. */ private static final double PIover6 = Math.PI / 6; /** * Constant for PI divided by 12. */ private static final double PIover12 = Math.PI / 12; /** * Constant used in the <code>atan</code> calculation. */ private static final double ATAN_CONSTANT = 1.732050807569; /** * Returns the arc cosine of an angle, in the range of 0.0 through <code>Math.PI</code>. * Special case: * <ul> * <li>If the argument is <code>NaN</code> or its absolute value is greater than 1, * then the result is <code>NaN</code>. * </ul> * * @param a - the value whose arc cosine is to be returned. * @return the arc cosine of the argument. */ public static double acos(double a) { // Special case. if (Double.isNaN(a) || Math.abs(a) > 1.0) { return Double.NaN; } // Calculate the arc cosine. double aSquared = a * a; double arcCosine = atan2(Math.sqrt(1 - aSquared), a); return arcCosine; } /** * Returns the arc sine of an angle, in the range of <code>-Math.PI/2</code> through * <code>Math.PI/2</code>. Special cases: * <ul> * <li>If the argument is <code>NaN</code> or its absolute value is greater than 1, * then the result is <code>NaN</code>. * <li>If the argument is zero, then the result is a zero with the same sign * as the argument. * </ul> * * @param a - the value whose arc sine is to be returned. * @return the arc sine of the argument. */ public static double asin(double a) { // Special cases. if (Double.isNaN(a) || Math.abs(a) > 1.0) { return Double.NaN; } if (a == 0.0) { return a; } // Calculate the arc sine. double aSquared = a * a; double arcSine = atan2(a, Math.sqrt(1 - aSquared)); return arcSine; } /** * Returns the arc tangent of an angle, in the range of <code>-Math.PI/2</code> * through <code>Math.PI/2</code>. Special cases: * <ul> * <li>If the argument is <code>NaN</code>, then the result is <code>NaN</code>. * <li>If the argument is zero, then the result is a zero with the same * sign as the argument. * </ul> * <p> * A result must be within 1 ulp of the correctly rounded result. Results * must be semi-monotonic. * * @param a - the value whose arc tangent is to be returned. * @return the arc tangent of the argument. */ public static double atan(double a) { // Special cases. if (Double.isNaN(a)) { return Double.NaN; } if (a == 0.0) { return a; } // Compute the arc tangent. boolean negative = false; boolean greaterThanOne = false; int i = 0; if (a < 0.0) { a = -a; negative = true; } if (a > 1.0) { a = 1.0 / a; greaterThanOne = true; } double t; for (; a > PIover12; a *= t) { i++; t = a + ATAN_CONSTANT; t = 1.0 / t; a *= ATAN_CONSTANT; a--; } double aSquared = a * a; double arcTangent = aSquared + 1.4087812; arcTangent = 0.55913709 / arcTangent; arcTangent += 0.60310578999999997; arcTangent -= 0.051604539999999997 * aSquared; arcTangent *= a; for (; i > 0; i--) { arcTangent += PIover6; } if (greaterThanOne) { arcTangent = PIover2 - arcTangent; } if (negative) { arcTangent = -arcTangent; } return arcTangent; } /** * Converts rectangular coordinates (x, y) to polar (r, <i>theta</i>). This method * computes the phase <i>theta</i> by computing an arc tangent of y/x in the range * of <i>-pi</i> to <i>pi</i>. Special cases: * <ul> * <li>If either argument is <code>NaN</code>, then the result is <code>NaN</code>. * <li>If the first argument is positive zero and the second argument is * positive, or the first argument is positive and finite and the second * argument is positive infinity, then the result is positive zero. * <li>If the first argument is negative zero and the second argument is * positive, or the first argument is negative and finite and the second * argument is positive infinity, then the result is negative zero. * <li>If the first argument is positive zero and the second argument is * negative, or the first argument is positive and finite and the second * argument is negative infinity, then the result is the <code>double</code> value * closest to <i>pi</i>. * <li>If the first argument is negative zero and the second argument is * negative, or the first argument is negative and finite and the second * argument is negative infinity, then the result is the <code>double</code> value * closest to <i>-pi</i>. * <li>If the first argument is positive and the second argument is positive * zero or negative zero, or the first argument is positive infinity and * the second argument is finite, then the result is the <code>double</code> value * closest to <i>pi</i>/2. * <li>If the first argument is negative and the second argument is positive * zero or negative zero, or the first argument is negative infinity and * the second argument is finite, then the result is the <code>double</code> value * closest to <i>-pi</i>/2. * <li>If both arguments are positive infinity, then the result is the double * value closest to <i>pi</i>/4. * <li>If the first argument is positive infinity and the second argument is * negative infinity, then the result is the double value closest to 3*<i>pi</i>/4. * <li>If the first argument is negative infinity and the second argument is * positive infinity, then the result is the double value closest to -<i>pi</i>/4. * <li>If both arguments are negative infinity, then the result is the double * value closest to -3*<i>pi</i>/4. * </ul> * <p> * A result must be within 2 ulps of the correctly rounded result. Results * must be semi-monotonic. * * @param y - the ordinate coordinate * @param x - the abscissa coordinate * @return the <i>theta</i> component of the point (r, <i>theta</i>) in polar * coordinates that corresponds to the point (x, y) in Cartesian coordinates. */ public static double atan2(double y, double x) { // Special cases. if (Double.isNaN(y) || Double.isNaN(x)) { return Double.NaN; } else if (Double.isInfinite(y)) { if (y > 0.0) // Positive infinity { if (Double.isInfinite(x)) { if (x > 0.0) { return PIover4; } else { return 3.0 * PIover4; } } else if (x != 0.0) { return PIover2; } } else // Negative infinity { if (Double.isInfinite(x)) { if (x > 0.0) { return -PIover4; } else { return -3.0 * PIover4; } } else if (x != 0.0) { return -PIover2; } } } else if (y == 0.0) { if (x > 0.0) { return y; } else if (x < 0.0) { return Math.PI; } } else if (Double.isInfinite(x)) { if (x > 0.0) // Positive infinity { if (y > 0.0) { return 0.0; } else if (y < 0.0) { return -0.0; } } else // Negative infinity { if (y > 0.0) { return Math.PI; } else if (y < 0.0) { return -Math.PI; } } } else if (x == 0.0) { if (y > 0.0) { return PIover2; } else if (y < 0.0) { return -PIover2; } } // Implementation a simple version ported from a PASCAL implementation: // http://everything2.com/index.pl?node_id=1008481 double arcTangent; // Use arctan() avoiding division by zero. if (Math.abs(x) > Math.abs(y)) { arcTangent = atan(y / x); } else { arcTangent = atan(x / y); // -PI/4 <= a <= PI/4 if (arcTangent < 0) { arcTangent = -PIover2 - arcTangent; // a is negative, so we're adding } else { arcTangent = PIover2 - arcTangent; } } // Adjust result to be from [-PI, PI] if (x < 0) { if (y < 0) { arcTangent = arcTangent - Math.PI; } else { arcTangent = arcTangent + Math.PI; } } return arcTangent; } /** * Returns the closest <code>int</code> to the argument. The * result is rounded to an integer by adding 1/2, taking the * floor of the result, and casting the result to type <code>int</code>. * In other words, the result is equal to the value of the expression: * <p> * <pre>(int)Math.floor(a + 0.5f)</pre> * <p> * Special cases: * <ul> * <li>If the argument is NaN, the result is 0. * <li>If the argument is negative infinity or any value less than or * equal to the value of <code>Integer.MIN_VALUE</code>, the result is * equal to the value of <code>Integer.MIN_VALUE</code>. * <li>If the argument is positive infinity or any value greater than or * equal to the value of <code>Integer.MAX_VALUE</code>, the result is * equal to the value of <code>Integer.MAX_VALUE</code>. * </ul> * * @param a - a floating-point value to be rounded to an integer. * @return the value of the argument rounded to the nearest <code>int</code> value. */ public static int round(float a) { return (int) Math.floor(a + 0.5f); } /** * Returns the closest <code>long</code> to the argument. The result * is rounded to an integer by adding 1/2, taking the floor of the * result, and casting the result to type <code>long</code>. In other * words, the result is equal to the value of the expression: * <p> * <pre>(long)Math.floor(a + 0.5d)</pre> * <p> * Special cases: * <ul> * <li>If the argument is NaN, the result is 0. * <li>If the argument is negative infinity or any value less than or * equal to the value of <code>Long.MIN_VALUE</code>, the result is * equal to the value of <code>Long.MIN_VALUE</code>. * <li>If the argument is positive infinity or any value greater than or * equal to the value of <code>Long.MAX_VALUE</code>, the result is * equal to the value of <code>Long.MAX_VALUE</code>. * </ul> * * @param a - a floating-point value to be rounded to a <code>long</code>. * @return the value of the argument rounded to the nearest <code>long</code> value. */ public static long round(double a) { return (long) Math.floor(a + 0.5); } }