Mega Code Archive

 
Categories / Java / Development Class
 

Implements the methods which are in the standard J2SEs Math class, but are not in in J2MEs

//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 );   } }