MicroFloat.java
上传用户:hygd004
上传日期:2022-07-01
资源大小:246k
文件大小:45k
源码类别:

J2ME

开发平台:

Java

  1. // $Id: MicroFloat.java,v 1.2 2004/08/03 04:57:42 Dave Exp $
  2. /*
  3.  * Float.java
  4.  * Copyright (C) 2003, 2004 David Clausen
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version 2
  9.  * of the License, or (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  *
  20.  */
  21. package net.dclausen.microfloat;
  22. //Download by http://www.codefans.net
  23. /**
  24.  * A software implementation of IEEE-754 single precision math which does not
  25.  * rely on the <code>float</code> data type. 
  26.  * This class overloads the <code>int</code> data type by storing 
  27.  * <code>float</code> data in it.
  28.  * See the 
  29.  * <a href="package-summary.html#package_description">package description</a> 
  30.  * for more information.
  31.  * <p>
  32.  * @author David Clausen
  33.  * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html">Float</a>
  34.  * @see MicroDouble
  35.  * @version $Revision: 1.2 $
  36.  */
  37. public final class MicroFloat {
  38.   /////////////////////////////////////////////////////////////////////////////
  39.   // General-purpose constants
  40.   /////////////////////////////////////////////////////////////////////////////
  41.   /**
  42.    * A constant representing the same value as 
  43.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#POSITIVE_INFINITY">Float.POSITIVE_INFINITY</a>
  44.    */
  45.   public  static final int POSITIVE_INFINITY = 0x7f800000;
  46.   /**
  47.    * A constant holding the same value as 
  48.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#NEGATIVE_INFINITY">Float.NEGATIVE_INFINITY</a>
  49.    */
  50.   public  static final int NEGATIVE_INFINITY = 0xff800000;
  51.   
  52.   /**
  53.    * A constant holding the same value as
  54.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#NaN">Float.NaN</a>
  55.    */
  56.   public  static final int NaN               = 0x7fc00000;
  57.   /**
  58.    * A constant holding the same value as 
  59.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#MAX_VALUE">Float.MAX_VALUE</a>
  60.    */
  61.   public  static final int MAX_VALUE         = 0x7f7fffff;
  62.   
  63.   /**
  64.    * A constant holding the same value as
  65.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#MIN_VALUE">Float.MIN_VALUE</a>
  66.    */
  67.   public  static final int MIN_VALUE         = 0x00000001;
  68.   /**
  69.    * A single-precision version of {@link MicroDouble#E}
  70.    */
  71.   public  static final int E                 = 0x402df854;
  72.   /**
  73.    * A single-precision version of {@link MicroDouble#PI}
  74.    */
  75.   public  static final int PI                = 0x40490fdb;
  76.   
  77.   // Other constants needed internally, and exposed as a convenience.
  78.   
  79.   /** A constant holding the value of 0.0f */
  80.   public static final int ZERO              = 0x00000000;
  81.   /** A constant holding the value of -0.0f */
  82.   public static final int NEGATIVE_ZERO     = 0x80000000;
  83.   /** A constant holding the value of 1.0f */
  84.   public static final int ONE               = 0x3f800000;
  85.   /** A constant holding the value of 2.0f */
  86.   public static final int TWO               = 0x40000000;
  87.   /** A constant holding the value of 0.5f */
  88.   public static final int ONE_HALF          = 0x3f000000;
  89.   
  90.   /////////////////////////////////////////////////////////////////////////////
  91.   // Packing and unpacking the IEEE-754 single precision format
  92.   /////////////////////////////////////////////////////////////////////////////
  93.   private static final int ABS_MASK          = 0x7fffffff;
  94.   private static final int SIGN_MASK         = 0x80000000; // 1 bit
  95.   private static final int EXPONENT_MASK     = 0x7f800000; // 8 bits
  96.   private static final int FRACTION_MASK     = 0x007fffff; // 23 bits
  97.   private static final int IMPLIED_ONE       = 0x00800000; // 24th bit
  98.   /** @return true iff d is negative */
  99.   static boolean unpackSign(int f) {
  100.     return (f < 0);
  101.   }
  102.   /** @return an integer in the range [-150, 105] */
  103.   static int unpackExponent(int f) {
  104.     return ((f >> 23) & 0xff) - 150;
  105.   }
  106.   
  107.   /** @return an integer in the range [0, 0x00ffffff] */
  108.   static int unpackMantissa(int f) {
  109.     if ((f & EXPONENT_MASK) == 0) {
  110.       return ((f & FRACTION_MASK) << 1);
  111.     } else {
  112.       return ((f & FRACTION_MASK) | IMPLIED_ONE);
  113.     }
  114.   }
  115.   /** 
  116.    * @return the float which most closely represents the given base-2 mantissa
  117.    *         and exponent
  118.    */
  119.   static int pack(boolean negative, int exponent, int mantissa) {
  120.     // left align mantissa
  121.     int shift = BitUtils.countLeadingZeros(mantissa);
  122.     mantissa <<= shift;
  123.     exponent -= shift;
  124.     return pack2(negative, exponent, mantissa);
  125.   }
  126.   /** 
  127.    * @return the float which most closely represents the given base-2 mantissa
  128.    *         and exponent
  129.    */
  130.   static int pack(boolean negative, int exponent, long mantissa) {
  131.     // shift mantissa so that it is left-aligned when cast to an int
  132.     int shift = 32 - BitUtils.countLeadingZeros(mantissa);
  133.     exponent += shift;
  134.     if (shift > 0) {
  135.       mantissa = BitUtils.stickyRightShift(mantissa, shift);
  136.     } else if (shift < 0) {
  137.       mantissa <<= -shift;
  138.     }
  139.     return pack2(negative, exponent, (int) mantissa);
  140.   }
  141.   /**
  142.    * @param mantissa must be left aligned (or zero)
  143.    */
  144.   private static int pack2(boolean negative, int exponent, int mantissa) {
  145.     // reduce precision of mantissa, rounding if necessary
  146.     if (mantissa != 0) {
  147.       if (exponent < -157) {
  148.         // subnormal
  149.         mantissa = BitUtils.roundingRightShift(mantissa, -149 - exponent);
  150.       } else {
  151.         // normal
  152.         mantissa = BitUtils.roundingRightShift(mantissa, 8);
  153.         if (mantissa == 0x1000000) {
  154.           // oops, the rounding carried into the 25th bit
  155.           mantissa = 0x800000;
  156.           exponent++;
  157.         }
  158.         // pack the exponent
  159.         if (exponent > 96) {
  160.           mantissa = POSITIVE_INFINITY;
  161.         } else {
  162.           mantissa ^= IMPLIED_ONE;
  163.           mantissa |= (exponent + 158) << 23;
  164.         }
  165.       }
  166.     }
  167.     // pack the sign bit
  168.     if (negative) {
  169.       mantissa |= SIGN_MASK;
  170.     }
  171.     
  172.     return mantissa;
  173.   }
  174.   
  175.   /////////////////////////////////////////////////////////////////////////////
  176.   // Simple tests 
  177.   /////////////////////////////////////////////////////////////////////////////
  178.   /**
  179.    * Mimics 
  180.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#isNaN(float)">Float.isNaN(float)</a>
  181.    */
  182.   public static boolean isNaN(int f) {
  183.     return ((f & ABS_MASK) > POSITIVE_INFINITY);
  184.   }
  185.   /**
  186.    * Mimics
  187.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#isInfinite(float)">Float.isInfinite(float)</a>
  188.    */
  189.   public static boolean isInfinite(int f) {
  190.     return ((f & ABS_MASK) == POSITIVE_INFINITY);
  191.   }
  192.   
  193.   /**
  194.    * Returns <code>true</code> if the specified number has zero
  195.    * magnitude, <code>false</code> otherwise.
  196.    *
  197.    * @param   f   the <code>float</code> value to be tested.
  198.    * @return  <code>true</code> if the value of the argument is positive
  199.    *          zero or negative zero; <code>false</code> otherwise.
  200.    */
  201.   public static boolean isZero(int f) {
  202.     return ((f & ABS_MASK) == 0);
  203.   }
  204.   
  205.   /////////////////////////////////////////////////////////////////////////////
  206.   // Sign changes
  207.   /////////////////////////////////////////////////////////////////////////////
  208.   
  209.   /**
  210.    * Mimics 
  211.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#abs(float)">Math.abs(float)</a>
  212.    */
  213.   public static int abs(int f) {
  214.     //if (isNaN(f)) {
  215.     //  return NaN;
  216.     //}
  217.     return (f & ABS_MASK);
  218.   }
  219.   /**
  220.    * Returns the negation of a <code>float</code> value.
  221.    * Special cases:
  222.    * <ul>
  223.    * <li>If the argument is negative zero, the result is positive zero.
  224.    * <li>If the argument is positive zero, the result is negative zero.
  225.    * <li>If the argument is negative infinity, the result is positive infinity.
  226.    * <li>If the argument is positive infinity, the result is negative infinity.
  227.    * <li>If the argument is NaN, the result is NaN.</ul>
  228.    * <p>
  229.    * This method takes the place of the unary <code>-</code> operator.
  230.    *
  231.    * @param   f   the <code>float</code> value whose negated value is to be 
  232.    *              determined
  233.    * @return  the negation of the argument.
  234.    */
  235.   public static int negate(int f) {
  236.     if (isNaN(f)) {
  237.       return NaN;
  238.     }
  239.     return (f ^ SIGN_MASK);
  240.   }
  241.   
  242.   /////////////////////////////////////////////////////////////////////////////
  243.   // Comparison
  244.   /////////////////////////////////////////////////////////////////////////////
  245.   /**
  246.    * Returns <code>true</code> if the specified numbers are considered equal
  247.    * according to 
  248.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5198">section 15.21.1
  249.    * of the JLS</a>.  Special cases:
  250.    * <ul>
  251.    * <li>If either operand is NaN, then the result is false
  252.    * <li>Positive zero and negative zero are considered equal
  253.    * </ul>
  254.    * <p>
  255.    * This method takes the place of the <code>==</code> operator.
  256.    *
  257.    * @param   f1   the first <code>float</code> value to be compared.
  258.    * @param   f2   the second <code>float</code> value to be compared.
  259.    * @return  <code>true</code> if the two values are considered equal;
  260.    *          <code>false</code> otherwise.
  261.    */
  262.   public static boolean eq(int f1, int f2) {
  263.     return (((f1 == f2) && (! isNaN(f1))) || (isZero(f1) && isZero(f2)));
  264.   }
  265.   
  266.   /**
  267.    * Returns <code>true</code> if the specified numbers are considered unequal
  268.    * according to 
  269.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5198">section
  270.    * 15.21.1 of the JLS</a>.  Special cases:
  271.    * <ul>
  272.    * <li>If either operand is NaN, then the result is true
  273.    * <li>Positive zero and negative zero are considered equal
  274.    * </ul>
  275.    * The value returned by <code>ne</code> is always the opposite of the value
  276.    * returned by <code>eq</code> for the same arguments.
  277.    * <p>
  278.    * This method takes the place of the <code>!=</code> operator.
  279.    *
  280.    * @param   f1   the first <code>float</code> value to be compared.
  281.    * @param   f2   the second <code>float</code> value to be compared.
  282.    * @return  <code>true</code> if the two values are considered equal;
  283.    *          <code>false</code> otherwise.
  284.    */
  285.   public static boolean ne(int f1, int f2) {
  286.     return (! eq(f1, f2));
  287.   }
  288.   /**
  289.    * Returns <code>true</code> if the first argument is considered less than
  290.    * the second argument according to 
  291.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#153654">section
  292.    * 15.20.1 of the JLS</a>.  Special cases:
  293.    * <ul>
  294.    * <li>If either operand is NaN, then the result is false
  295.    * <li>Positive zero and negative zero are considered equal
  296.    * <li>Negative infinity is conisdered less than all other values except NaN
  297.    * <li>Positive infinity is conisdered greater than all other values except NaN
  298.    * </ul>
  299.    * <p>
  300.    * This method takes the place of the <code>&lt;</code> operator.
  301.    *
  302.    * @param   f1   the first <code>float</code> value to be compared.
  303.    * @param   f2   the second <code>float</code> value to be compared.
  304.    * @return  <code>true</code> if the first value is less than the second value;
  305.    *          <code>false</code> otherwise.
  306.    */
  307.   public static boolean lt(int f1, int f2) {
  308.     if (isNaN(f1) || isNaN(f2)) {
  309.       return false;
  310.     } else if (f2 == ZERO) {
  311.       f2 = NEGATIVE_ZERO;
  312.     }
  313.     return (cmp(f1, f2) < 0);
  314.   }
  315.   
  316.   /**
  317.    * Returns <code>true</code> if the first argument is considered less than
  318.    * or equal to the second argument according to 
  319.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#153654">section
  320.    * 15.20.1 of the JLS</a>.  Special cases:
  321.    * <ul>
  322.    * <li>If either operand is NaN, then the result is false
  323.    * <li>Positive zero and negative zero are considered equal
  324.    * <li>Negative infinity is conisdered less than all other values except NaN
  325.    * <li>Positive infinity is conisdered greater than all other values except NaN
  326.    * </ul>
  327.    * <p>
  328.    * This method takes the place of the <code>&lt;=</code> operator.
  329.    *
  330.    * @param   f1   the first <code>float</code> value to be compared.
  331.    * @param   f2   the second <code>float</code> value to be compared.
  332.    * @return  <code>true</code> if the first value is less than or equal to 
  333.    *          the second value; <code>false</code> otherwise.
  334.    */
  335.   public static boolean le(int f1, int f2) {
  336.     if (isNaN(f1) || isNaN(f2)) {
  337.       return false;
  338.     } else if (f2 == NEGATIVE_ZERO) {
  339.       f2 = ZERO;
  340.     }
  341.     return (cmp(f1, f2) <= 0);
  342.   }
  343.   /**
  344.    * Returns <code>true</code> if the first argument is considered greater than
  345.    * the second argument according to 
  346.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#153654">section
  347.    * 15.20.1 of the JLS</a>.  Special cases:
  348.    * <ul>
  349.    * <li>If either operand is NaN, then the result is false
  350.    * <li>Positive zero and negative zero are considered equal
  351.    * <li>Negative infinity is conisdered less than all other values except NaN
  352.    * <li>Positive infinity is conisdered greater than all other values except NaN
  353.    * </ul>
  354.    * <p>
  355.    * This method takes the place of the <code>&gt;</code> operator.
  356.    *
  357.    * @param   f1   the first <code>float</code> value to be compared.
  358.    * @param   f2   the second <code>float</code> value to be compared.
  359.    * @return  <code>true</code> if the first value is greater than the second value;
  360.    *          <code>false</code> otherwise.
  361.    */
  362.   public static boolean gt(int f1, int f2) {
  363.     if (isNaN(f1) || isNaN(f2)) {
  364.       return false;
  365.     } else if (f1 == ZERO) {
  366.       f1 = NEGATIVE_ZERO;
  367.     }
  368.     return (cmp(f1, f2) > 0);
  369.   }
  370.   
  371.   /**
  372.    * Returns <code>true</code> if the first argument is considered greater than
  373.    * or equal to the second argument according to 
  374.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#153654">section
  375.    * 15.20.1 of the JLS</a>.  Special cases:
  376.    * <ul>
  377.    * <li>If either operand is NaN, then the result is false
  378.    * <li>Positive zero and negative zero are considered equal
  379.    * <li>Negative infinity is conisdered less than all other values except NaN
  380.    * <li>Positive infinity is conisdered greater than all other values except NaN
  381.    * </ul>
  382.    * <p>
  383.    * This method takes the place of the <code>&gt;=</code> operator.
  384.    *
  385.    * @param   f1   the first <code>float</code> value to be compared.
  386.    * @param   f2   the second <code>float</code> value to be compared.
  387.    * @return  <code>true</code> if the first value is greater than or equal to 
  388.    *          the second value; <code>false</code> otherwise.
  389.    */
  390.   public static boolean ge(int f1, int f2) {
  391.     if (isNaN(f1) || isNaN(f2)) {
  392.       return false;
  393.     } else if (f1 == NEGATIVE_ZERO) {
  394.       f1 = ZERO;
  395.     }
  396.     return (cmp(f1, f2) >= 0);
  397.   }
  398.   /**
  399.    * Mimics 
  400.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#compare(float, float)">Float.compare(float, float)</a>.
  401.    * <p>
  402.    * Note that when using this method (as well as <code>Float.compare</code>),
  403.    * the following rules apply:
  404.    * <ul><li>
  405.    * <code>NaN</code> is considered 
  406.    * to be equal to itself and greater than all other
  407.    * <code>float</code> values (including
  408.    * <code>POSITIVE_INFINITY</code>).
  409.    * <li>
  410.    * <code>0.0</code> is considered to be greater
  411.    * than <code>-0.0</code>.
  412.    * </ul>
  413.    */
  414.   public static int compare(int f1, int f2) {
  415.     boolean n1 = isNaN(f1);
  416.     boolean n2 = isNaN(f2);
  417.     if (n1 || n2) {
  418.       if (n1 && n2) {
  419.         return 0;
  420.       }
  421.       return (n1 ? 1 : -1);
  422.     }
  423.     return cmp(f1, f2);
  424.   }
  425.   /**
  426.    * Mimics 
  427.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#max(float, float)">Math.max(float, float)</a>.
  428.    */
  429.   public static int max(int f1, int f2) {
  430.     if (isNaN(f1) || isNaN(f2)) {
  431.       return NaN;
  432.     }
  433.     return ((cmp(f1, f2) < 0) ? f2 : f1);
  434.   }
  435.   /**
  436.    * Mimics 
  437.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#min(float, float)">Math.min(float, float)</a>.
  438.    */
  439.   public static int min(int f1, int f2) {
  440.     if (isNaN(f1) || isNaN(f2)) {
  441.       return NaN;
  442.     }
  443.     return ((cmp(f1, f2) > 0) ? f2 : f1);
  444.   }
  445.   private static int cmp(int f1, int f2) {
  446.     if (f1 < 0) {
  447.       if (f2 < 0) {
  448.         return f2 - f1;
  449.       } else {
  450.         return -1;
  451.       }
  452.     } else if (f2 < 0) {
  453.       return 1;
  454.     } else {
  455.       return f1 - f2;
  456.     }
  457.   }
  458.   /////////////////////////////////////////////////////////////////////////////
  459.   // Type conversion
  460.   /////////////////////////////////////////////////////////////////////////////
  461.   /** 
  462.    * Convert the given <code>int</code> to a <code>float</code> as would happen
  463.    * in a casting operation specified by 
  464.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
  465.    * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
  466.    * will not result in a loss of magnitude, but might result in a loss of
  467.    * precision.
  468.    *
  469.    * @param x the <code>int</code> to be converted
  470.    * @return the <code>float</code> representation of the argument
  471.    */
  472.   public static int intToFloat(int x) {
  473.     if (x < 0) {
  474.       return pack(true, 0, -x);
  475.     }
  476.     return pack(false, 0, x);
  477.   }
  478.   
  479.   /** 
  480.    * Convert the given <code>long</code> to a <code>float</code> as would happen
  481.    * in a casting operation specified by 
  482.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
  483.    * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
  484.    * will not result in a loss of magnitude, but might result in a loss of
  485.    * precision.
  486.    *
  487.    * @param x the <code>long</code> to be converted
  488.    * @return the <code>float</code> representation of the argument
  489.    */
  490.   public static int longToFloat(long x) {
  491.     if (x < 0) {
  492.       return pack(true, 0, -x);
  493.     }
  494.     return pack(false, 0, x);
  495.   }
  496.   /** 
  497.    * Convert the given <code>double</code> to a <code>float</code> as would happen
  498.    * in a casting operation specified by 
  499.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
  500.    * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
  501.    * may result in a loss of magnitude and/or precision.
  502.    *
  503.    * @param d the <code>double</code> to be converted
  504.    * @return the <code>float</code> representation of the argument
  505.    */
  506.   public static int doubleToFloat(long d) {
  507.     if (MicroDouble.isNaN(d)) {
  508.       return NaN;
  509.     }
  510.     boolean n = MicroDouble.unpackSign(d);
  511.     if (MicroDouble.isZero(d)) {
  512.       return (n ? NEGATIVE_ZERO : ZERO);
  513.     } else if (MicroDouble.isInfinite(d)) {
  514.       return (n ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  515.     }
  516.     int x = MicroDouble.unpackExponent(d);
  517.     long m = MicroDouble.unpackMantissa(d);
  518.     return pack(n, x, m);
  519.   }
  520.   /** 
  521.    * Convert the given <code>float</code> to a <code>byte</code> as would happen
  522.    * in a casting operation specified by 
  523.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
  524.    * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
  525.    * may result in a loss of magnitude and/or precision.
  526.    * <p>
  527.    * Note that this is a non-intuitive conversion.  If the argument is outside
  528.    * of the range of the byte type, the result is basically meaningless.
  529.    *
  530.    * @param f the <code>float</code> to be converted
  531.    * @return the <code>byte</code> representation of the argument
  532.    */
  533.   public static byte byteValue(int f) {
  534.     long x = intValue(f);
  535.     return (byte) x;
  536.   }
  537.   /** 
  538.    * Convert the given <code>float</code> to a <code>short</code> as would happen
  539.    * in a casting operation specified by 
  540.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
  541.    * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
  542.    * may result in a loss of magnitude and/or precision.
  543.    * <p>
  544.    * Note that this is a non-intuitive conversion.  If the argument is outside
  545.    * of the range of the short type, the result is basically meaningless.
  546.    *
  547.    * @param f the <code>float</code> to be converted
  548.    * @return the <code>short</code> representation of the argument
  549.    */
  550.   public static short shortValue(int f) {
  551.     long x = intValue(f);
  552.     return (short) x;
  553.   }
  554.   /** 
  555.    * Convert the given <code>float</code> to an <code>int</code> as would happen
  556.    * in a casting operation specified by 
  557.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
  558.    * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
  559.    * may result in a loss of magnitude and/or precision.
  560.    *
  561.    * @param f the <code>float</code> to be converted
  562.    * @return the <code>int</code> representation of the argument
  563.    */
  564.   public static int intValue(int f) {
  565.     long x = longValue(f);
  566.     if (x >= Integer.MAX_VALUE) {
  567.       return Integer.MAX_VALUE;
  568.     } else if (x <= Integer.MIN_VALUE) {
  569.       return Integer.MIN_VALUE;
  570.     }
  571.     return (int) x;
  572.   }
  573.   
  574.   /** 
  575.    * Convert the given <code>float</code> to a <code>long</code> as would happen
  576.    * in a casting operation specified by 
  577.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
  578.    * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
  579.    * may result in a loss of magnitude and/or precision.
  580.    *
  581.    * @param f the <code>float</code> to be converted
  582.    * @return the <code>long</code> representation of the argument
  583.    */
  584.   public static long longValue(int f) {
  585.     if (isNaN(f)) {
  586.       return 0;
  587.     }
  588.     boolean n = unpackSign(f);
  589.     int x = unpackExponent(f);
  590.     long m = unpackMantissa(f);
  591.     if (x > 0) {
  592.       if ((x >= 63) || ((m >> (63 - x)) != 0))  {
  593.         return (n ? Long.MIN_VALUE : Long.MAX_VALUE);
  594.       }
  595.       m <<= x;
  596.     } else if (x <= -24) {
  597.       return 0;
  598.     } else {
  599.       m >>>= -x;
  600.     }
  601.     return (n ? -m : m);
  602.   }
  603.   /** 
  604.    * Convert the given <code>float</code> to a <code>double</code> as would happen
  605.    * in a casting operation specified by 
  606.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
  607.    * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
  608.    * will result in neither a loss of magnitude nor precision.
  609.    *
  610.    * @param f the <code>float</code> to be converted
  611.    * @return the <code>double</code> representation of the argument
  612.    */
  613.   public static long doubleValue(int f) {
  614.     return MicroDouble.floatToDouble(f);
  615.   }
  616.   
  617.   /////////////////////////////////////////////////////////////////////////////
  618.   // Basic arithmetic
  619.   /////////////////////////////////////////////////////////////////////////////
  620.   /**
  621.    * Returns the sum of the two <code>float</code> arguments according to 
  622.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510">section
  623.    * 15.18.2 of the JLS</a>.
  624.    * <p>
  625.    * This method takes the place of the binary <code>+</code> operator.
  626.    *
  627.    * @param   f1   the first <code>float</code> value to be summed.
  628.    * @param   f2   the second <code>float</code> value to be summed.
  629.    * @return  the sum of the two arguments
  630.    */
  631.   public static int add(int f1, int f2) {
  632.     if (isNaN(f1) || isNaN(f2)) {
  633.       return NaN;
  634.     }
  635.     
  636.     boolean n1 = unpackSign(f1);
  637.     boolean n2 = unpackSign(f2);
  638.     
  639.     // special handling of infinity
  640.     boolean i1 = isInfinite(f1);
  641.     boolean i2 = isInfinite(f2);
  642.     if (i1 || i2) {
  643.       if (i1 && i2) {
  644.         if (n1 != n2) {
  645.           // infinites of opposite sign -> NaN
  646.           return NaN;
  647.         } else {
  648.           // infinites of same sign -> infinity the same sign
  649.           return f1;
  650.         }
  651.       } else if (i1) {
  652.         return f1; // infinite + finite = infinite
  653.       } else {
  654.         return f2; // finite + infinite = infinite
  655.       }
  656.     }
  657.     
  658.     // special handling of zero
  659.     boolean z1 = isZero(f1);
  660.     boolean z2 = isZero(f2);
  661.     if (z1 || z2) {
  662.       if (z1 && z2) {
  663.         if (n1 != n2) {
  664.           // zeros of opposite sign -> positive zero
  665.           return ZERO;
  666.         } else {
  667.           return f1; // zeros of same sign -> zero of the same sign
  668.         }
  669.       } else if (z1) {
  670.         return f2; // zero + nonzero = nonzero
  671.       } else {
  672.         return f1; // nonzero + zero = nonzero
  673.       }
  674.     }
  675.     
  676.     // unpack, and add 3 guard digits
  677.     int m1 = unpackMantissa(f1) << 3;
  678.     int x1 = unpackExponent(f1) - 3;
  679.     int m2 = unpackMantissa(f2) << 3;
  680.     int x2 = unpackExponent(f2) - 3;
  681.     // make exponents equal
  682.     int dx = x1 - x2;
  683.     if (dx > 0) {
  684.       m2 = BitUtils.stickyRightShift(m2, dx);
  685.       x2 = x1;
  686.     } else if (dx < 0) {
  687.       m1 = BitUtils.stickyRightShift(m1, -dx);
  688.       x1 = x2;
  689.     }
  690.     // if the signs are different, negate the smaller mantissa and choose
  691.     // the sign of the larger
  692.     if (n1 ^ n2) { 
  693.       if (m1 > m2) {
  694.         m2 = -m2;
  695.       } else {
  696.         m1 = -m1;
  697.         n1 = n2;
  698.       }
  699.     }
  700.     
  701.     // add (or subtract) mantissas
  702.     m1 += m2;
  703.     // pack result, and handle special case of zero (which always returns +0.0) 
  704.     int f = pack(n1, x1, m1);
  705.     if (f == NEGATIVE_ZERO) {
  706.       return ZERO;
  707.     }
  708.     return f;
  709.   }
  710.   /**
  711.    * Returns the difference of the two <code>float</code> arguments according to 
  712.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510">section
  713.    * 15.18.2 of the JLS</a>.
  714.    * <p>
  715.    * This method takes the place of the binary <code>-</code> operator.
  716.    *
  717.    * @param   f1   the first <code>float</code> value 
  718.    * @param   f2   the second <code>float</code> value
  719.    * @return  the difference of the two arguments
  720.    */
  721.   public static int sub(int f1, int f2) {
  722.     return add(f1, negate(f2));
  723.   }
  724.   /**
  725.    * Returns the product of the two <code>float</code> arguments according to 
  726.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5036">section
  727.    * 15.17.1 of the JLS</a>.
  728.    * <p>
  729.    * This method takes the place of the <code>*</code> operator.
  730.    *
  731.    * @param   f1   the first <code>float</code> value
  732.    * @param   f2   the second <code>float</code> value
  733.    * @return  the product of the two arguments
  734.    */
  735.   public static int mul(int f1, int f2) {
  736.     if (isNaN(f1) || isNaN(f2)) {
  737.       return NaN;
  738.     }
  739.     boolean negative = unpackSign(f1) ^ unpackSign(f2);
  740.     
  741.     // special handling of infinity
  742.     if (isInfinite(f1) || isInfinite(f2)) {
  743.       if (isZero(f1) || isZero(f2)) {
  744.         return NaN;
  745.       } else {
  746.         return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  747.       }
  748.     }
  749.     
  750.     // unpack
  751.     int m1 = unpackMantissa(f1);
  752.     int x1 = unpackExponent(f1);
  753.     int m2 = unpackMantissa(f2);
  754.     int x2 = unpackExponent(f2);
  755.     
  756.     // compute the resultant exponent
  757.     x1 += x2;
  758.     
  759.     // compute the resultant mantissa using integer multiplication
  760.     long m = ((long) m1) * ((long) m2);
  761.     
  762.     // round and pack the result
  763.     return pack(negative, x1, m);
  764.   }
  765.   /**
  766.    * Returns the quotient of the two <code>float</code> arguments according to 
  767.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5047">section
  768.    * 15.17.2 of the JLS</a>.
  769.    * <p>
  770.    * This method takes the place of the <code>/</code> operator.
  771.    *
  772.    * @param   f1   the <code>float</code> dividend 
  773.    * @param   f2   the <code>float</code> divisor
  774.    * @return  the quotient of the two arguments
  775.    */
  776.   public static int div(int f1, int f2) {
  777.     if (isNaN(f1) || isNaN(f2)) {
  778.       return NaN;
  779.     }
  780.     boolean negative = unpackSign(f1) ^ unpackSign(f2);
  781.     
  782.     // special handling of infinity
  783.     boolean n1 = isInfinite(f1);
  784.     boolean n2 = isInfinite(f2);
  785.     if (n1 || n2) {
  786.       if (n1 && n2) {
  787.         return NaN;
  788.       } else if (n1) {
  789.         return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  790.       } else {
  791.         return (negative ? NEGATIVE_ZERO : ZERO);
  792.       }
  793.     }
  794.     // neither value is infinite
  795.     
  796.     // special handling of zero
  797.     n1 = isZero(f1);
  798.     n2 = isZero(f2);
  799.     if (n1 || n2) {
  800.       if (n1 && n2) {
  801.         return NaN;
  802.       } else if (n1) {
  803.         return (negative ? NEGATIVE_ZERO : ZERO);
  804.       } else {
  805.         return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  806.       }
  807.     }
  808.     // neither value is zero
  809.     
  810.     // unpack
  811.     int m1 = unpackMantissa(f1);
  812.     int x1 = unpackExponent(f1);
  813.     int m2 = unpackMantissa(f2);
  814.     int x2 = unpackExponent(f2);
  815.     // shift the dividend to the left to increase precision, then do an integer
  816.     // divide
  817.     int s = BitUtils.countLeadingZeros(m1) + 22;
  818.     long m3 = ((long) m1) << s;
  819.     int x = x1 - x2 - s;
  820.     long m = m3 / m2;
  821.     boolean r = ((m * m2) != m3);
  822.     // put a non-zero fraction into the sticky bit
  823.     if (r) {
  824.       m |= 1; 
  825.     }
  826.     return pack(negative, x, m);
  827.   }
  828.   /**
  829.    * Returns the remainder of the two <code>float</code> arguments according to 
  830.    * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#24956">section
  831.    * 15.17.3 of the JLS</a>.
  832.    * <p>
  833.    * This method takes the place of the <code>%</code> operator.
  834.    *
  835.    * @param   f1   the <code>float</code> dividend 
  836.    * @param   f2   the <code>float</code> divisor
  837.    * @return  the remainder of the two arguments
  838.    */
  839.   public static int mod(int f1, int f2) {
  840.     if (isNaN(f1) || isNaN(f2) || isInfinite(f1) || isZero(f2)) {
  841.       return NaN;
  842.     } else if (isZero(f1) || isInfinite(f2)) {
  843.       return f1;
  844.     }
  845.     
  846.     // unpack
  847.     int x1 = unpackExponent(f1);
  848.     int x2 = unpackExponent(f2);
  849.     if (x1 < x2) {
  850.       return f1;
  851.     }
  852.     boolean n = unpackSign(f1);
  853.     int m1 = unpackMantissa(f1);
  854.     int m2 = unpackMantissa(f2);
  855.     if (x1 == x2) {
  856.       m1 %= m2;
  857.     } else {
  858.       // reduce m1 by left shifting and modding until the exponents x1 and x2 are 
  859.       // equal
  860.       while (x1 != x2) {
  861.         int s = Math.min(39, x1 - x2);
  862.         x1 -= s;
  863.         m1 = (int) ((((long) m1) << s) % m2);
  864.       }
  865.     }
  866.     return pack(n, x1, m1);
  867.   }
  868.   /////////////////////////////////////////////////////////////////////////////
  869.   // Rounding
  870.   /////////////////////////////////////////////////////////////////////////////
  871.   /**
  872.    * Returns the <code>float</code> of greatest magnitude (furthest from zero)
  873.    * that is equal to a mathematical integer and which has a mignitude not
  874.    * greater than the argument's magnitude.  Special cases:
  875.    * <ul><li>If the argument value is already equal to a mathematical 
  876.    * integer, then the result is the same as the argument. 
  877.    * <li>If the argument is NaN or an infinity or positive zero or 
  878.    * negative zero, then the result is the same as the argument.</ul>
  879.    *
  880.    * @param   f   a <code>float</code> value.
  881.    * @return the <code>float</code> of greatest magnitude (furthest from zero)
  882.    *         whose magnitude is not greater than the argument's and which 
  883.    *         is equal to a mathematical integer.
  884.    */
  885.   public static int truncate(int f) {
  886.     return round(f, false, unpackSign(f));
  887.   }
  888.   /**
  889.    * Mimics 
  890.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#rint(double)">Math.rint(double)</a>, 
  891.    * using single precision.
  892.    */
  893.   public static int rint(int f) {
  894.     return round(f, true, false);
  895.   }
  896.   
  897.   /**
  898.    * Mimics
  899.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#floor(double)">Math.floor(double)</a>, 
  900.    * using single precision.
  901.    */
  902.   public static int floor(int f) {
  903.     return round(f, false, false);
  904.   }
  905.   
  906.   /**
  907.    * Mimics
  908.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#ceil(double)">Math.ceil(double)</a>, 
  909.    * using single precision.
  910.    */
  911.   public static int ceil(int f) {
  912.     return round(f, false, true);
  913.   }
  914.   /**
  915.    * Mimics
  916.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#round(double)">Math.round(double)</a>, 
  917.    * using single precision.
  918.    */
  919.   public static int round(int f) {
  920.     return intValue(floor(add(f, ONE_HALF)));
  921.   }
  922.   private static int round(int f, boolean round, boolean ceil) {
  923.     if (isNaN(f)) {
  924.       return NaN;
  925.     } else if (isZero(f) || isInfinite(f)) {
  926.       return f;
  927.     }
  928.     int x = unpackExponent(f);
  929.     if (x >= 0) {
  930.       return f;
  931.     }
  932.     boolean n = unpackSign(f);
  933.     int m = unpackMantissa(f);
  934.     if (round) {
  935.       m = BitUtils.roundingRightShift(m, -x);
  936.     } else {
  937.       int r;
  938.       if (x <= -32) {
  939.         r = m;
  940.         m = 0;
  941.       } else {
  942.         r = m << (32 + x);
  943.         m >>>= -x;
  944.       }
  945.       if ((n ^ ceil) && (r != 0)) {
  946.         m++;
  947.       }
  948.     }
  949.     return pack(n, 0, m);
  950.   }
  951.   /////////////////////////////////////////////////////////////////////////////
  952.   // String conversion
  953.   /////////////////////////////////////////////////////////////////////////////
  954.   // decimal -> binary
  955.   
  956.   // base 2 mantissas for 10**-54 through 10**38, at intervals of 100
  957.   private static final int[] pow10m = {
  958.           0xc428d05b, 0x993fe2c7, 0xef73d257, 0xbb127c54, 0x92267121, 
  959.           0xe45c10c4, 0xb267ed19, 0x8b61313c, 0xd9c7dced, 0xaa242499, 
  960.           0x84ec3c98, 0xcfb11ead, 0xa2425ff7, 0xfd87b5f3, 0xc6120625, 
  961.           0x9abe14cd, 0xf1c90081, 0xbce50865, 0x9392ee8f, 0xe69594bf, 
  962.           0xb424dc35, 0x8cbccc09, 0xdbe6fecf, 0xabcc7712, 0x8637bd06, 
  963.           0xd1b71759, 0xa3d70a3d, 0x80000000, 0xc8000000, 0x9c400000, 
  964.           0xf4240000, 0xbebc2000, 0x9502f900, 0xe8d4a510, 0xb5e620f5, 
  965.           0x8e1bc9bf, 0xde0b6b3a, 0xad78ebc6, 0x87867832, 0xd3c21bcf, 
  966.           0xa56fa5ba, 0x813f3979, 0xc9f2c9cd, 0x9dc5ada8, 0xf684df57, 
  967.           0xc097ce7c, 0x96769951,
  968.   };
  969.   
  970.   // base 2 exponents for 10**-54 through 10**38, at intervals of 100
  971.   private static final short[] pow10x = {
  972.           -211, -204, -198, -191, -184, -178, -171, -164, 
  973.           -158, -151, -144, -138, -131, -125, -118, -111, 
  974.           -105, -98, -91, -85, -78, -71, -65, -58, 
  975.           -51, -45, -38, -31, -25, -18, -12, -5, 
  976.           2, 8, 15, 22, 28, 35, 42, 48, 
  977.           55, 62, 68, 75, 81, 88, 95,
  978.   };
  979.           
  980.   private static int decToFloat(boolean negative, int base10x, int base10m) {
  981.     if (base10m == 0) {
  982.       return (negative ? NEGATIVE_ZERO : ZERO);
  983.     }
  984.     // maximize base10m to ensure consistency between toString and parseFloat
  985.     while ((base10m > 0) && (base10m <= 0x19999999)) { // (Integer.MAX_VALUE / 5))) {
  986.       base10m = (base10m << 3) + (base10m << 1);
  987.       base10x--;
  988.     }
  989.     // base10x needs to be a multiple of 2, because the tables are
  990.     // spaced at intervals of 100 (not 10).
  991.     base10x += 54;
  992.     boolean mod = ((base10x & 1) != 0);
  993.     base10x >>= 1;
  994.     if (base10x < 0) { // -54
  995.       return (negative ? NEGATIVE_ZERO : ZERO);
  996.     } else if (base10x > 46) { // 38
  997.       return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  998.     }
  999.     int base2x = pow10x[base10x];
  1000.     long base2m = (base10m & 0xffffffffL) * (pow10m[base10x] & 0xffffffffL);
  1001.     if (mod) {
  1002.       if (base2m < 0) {
  1003.         base2m >>>= 1;
  1004.         base2x++;
  1005.       }
  1006.       base2m += base2m >>> 2;
  1007.       base2x += 3;
  1008.     }
  1009.     return pack(negative, base2x, base2m);
  1010.   }
  1011.   /**
  1012.    * Mimics
  1013.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#parseFloat(String)">Float.parseFloat(String)</a>.
  1014.    * <p>
  1015.    * <b>This implementation is known to be inaccurate, and 
  1016.    * does not always return the same value as 
  1017.    * <code>Float.parseFloat</code>.</b>  However the difference should be no 
  1018.    * greater than 1 ulp.
  1019.    *
  1020.    * @exception  NumberFormatException  if the string does not contain a
  1021.    *               parsable number.
  1022.    */
  1023.   public static int parseFloat(String s) {
  1024.     // remove leading & trailing whitespace
  1025.     s = s.trim().toUpperCase();
  1026.     
  1027.     // check length
  1028.     int len = s.length();
  1029.     if (len == 0) {
  1030.       throw new NumberFormatException(s);
  1031.     }
  1032.     
  1033.     // check for NaN
  1034.     if ("NAN".equals(s)) {
  1035.       return NaN;
  1036.     }
  1037.     
  1038.     // begin parsing, one character at a time
  1039.     int idx = 0;
  1040.     
  1041.     // read sign
  1042.     boolean negative = false;
  1043.     char c = s.charAt(0);
  1044.     negative = (c == '-');
  1045.     if (negative || (c == '+')) {
  1046.       idx = 1;
  1047.     }
  1048.     // check for "Infinity"
  1049.     if (idx < len) {
  1050.       c = s.charAt(idx);
  1051.       if ((c == 'I') || (c == 'i')) {
  1052.         if ("INFINITY".equals(s.substring(idx))) {
  1053.           return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
  1054.         }
  1055.       }
  1056.     }
  1057.     // read Digits.Digits
  1058.     int mantissa = 0;
  1059.     int exponent = 0;
  1060.     int fractionChars = 0;
  1061.     boolean sticky = false;
  1062.     boolean readingFraction = false;
  1063.     while (idx < len) {
  1064.       c = s.charAt(idx);
  1065.       if (c == '.') {
  1066.         if (readingFraction) {
  1067.           throw new NumberFormatException(s);
  1068.         }
  1069.         readingFraction = true;
  1070.       } else if ((c < '0') || (c > '9')) {
  1071.         break;
  1072.       } else {
  1073.         fractionChars++;
  1074.         if (mantissa <= 0x19999998) { // ((Integer.MAX_VALUE / 5) - 1)) { 
  1075.           mantissa = (mantissa << 3) + (mantissa << 1) + (c - '0');
  1076.           if (readingFraction) {
  1077.             exponent--;
  1078.           }
  1079.         } else {
  1080.           if (! readingFraction) {
  1081.             exponent++;
  1082.           }
  1083.           sticky |= (c != '0');
  1084.         }
  1085.       }
  1086.       idx++;
  1087.     }
  1088.     if (fractionChars == 0) {
  1089.       throw new NumberFormatException(s);
  1090.     }
  1091.     
  1092.     // read exponent
  1093.     if (((idx + 1) < len) && ((s.charAt(idx) == 'E') || (s.charAt(idx) == 'e'))) {
  1094.       try {
  1095.         exponent += Integer.parseInt(s.substring(idx + 1));
  1096.       } catch (NumberFormatException e) {
  1097.         throw new NumberFormatException(s);
  1098.       }
  1099.       idx = len;
  1100.     } else if (idx != len) {
  1101.       // check that we parsed the entire string
  1102.       throw new NumberFormatException(s);
  1103.     }
  1104.     // convert the decimal to a float
  1105.     return decToFloat(negative, exponent, mantissa);
  1106.   }
  1107.   // binary -> decimal
  1108.   
  1109.   // base 10 mantissas for 2**-150 through 2**98, at intervals of 2**8
  1110.   private static final int[] pow2m = {
  1111.           0xb35dbf82, 0x2deaf18a, 0x758ca7c7, 
  1112.           0x1e17b843, 0x4d0985cb, 0xc5371912, 
  1113.           0x327cb273, 0x813f3979, 0x21165458, 
  1114.           0x54b40b20, 0xd8d726b7, 0x3782dacf, 
  1115.           0x8e1bc9bf, 0x246139cb, 0x5d21dba0, 
  1116.           0xee6b2800, 0x3d090000, 0x9c400000, 
  1117.           0x28000000, 0x66666666, 0x1a36e2eb, 
  1118.           0x431bde83, 0xabcc7712, 0x2bfaffc3, 
  1119.           0x709709a1, 0x1cd2b298, 0x49c97747, 
  1120.           0xbce50865, 0x305b6680, 0x7bcb43d7, 
  1121.           0x1fb0f6be, 0x51212ffc, 
  1122.   };
  1123.   // base 10 exponents for 2 ^ -150 through 2 ^ 98, at intervals of 2 ^ 8
  1124.   private static final byte[] pow2x = {
  1125.           -45, -42, -40, -37, -35, -33, -30, -28, 
  1126.           -25, -23, -21, -18, -16, -13, -11, -9, 
  1127.           -6, -4, -1, 1, 4, 6, 8, 11, 
  1128.           13, 16, 18, 20, 23, 25, 28, 30, 
  1129.   };
  1130.   /**
  1131.    * Mimics
  1132.    * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Float.html#toString(float)">Float.toString(float)</a>.
  1133.    * <p>
  1134.    * <b>This implementation is known to be inaccurate, and 
  1135.    * does not always return the same value as 
  1136.    * <code>Float.toString</code>.</b>  However the difference should be no 
  1137.    * greater than 1 ulp.
  1138.    */
  1139.   public static String toString(int f) {
  1140.     if (isNaN(f)) {
  1141.       return "NaN";
  1142.     }
  1143.     boolean n = unpackSign(f);
  1144.     StringBuffer sb = new StringBuffer(15);
  1145.     if (n) {
  1146.       sb.append('-');
  1147.     }
  1148.     if (isZero(f)) {
  1149.       sb.append("0.0");
  1150.       return sb.toString();
  1151.     } else if (isInfinite(f)) {
  1152.       sb.append("Infinity");
  1153.       return sb.toString();
  1154.     }
  1155.     // convert from base 2 to base 10
  1156.     int base2x = unpackExponent(f);
  1157.     int base2m = unpackMantissa(f);
  1158.     int idx = base2x + 150;
  1159.     int dx = idx & 7;
  1160.     base2m <<= dx;
  1161.     idx >>= 3;
  1162.     int base10x = pow2x[idx];
  1163.     while (base2m <= 0xccccccc) {
  1164.       base2m = (base2m << 3) + (base2m << 1); // base2m *= 10;
  1165.       base10x--;
  1166.     }
  1167.     long base10ml = base2m * (pow2m[idx] & 0xffffffffL);
  1168.     int base10m = (int) (base10ml >>> 32);
  1169.     if ((base10ml << 32) < 0) {
  1170.       base10m++;
  1171.     }
  1172.     // reduce the number of digits in m10 
  1173.     boolean roundedUp = false;
  1174.     while (true) {
  1175.       int r = base10m % 10;
  1176.       int mt = base10m / 10;
  1177.       int xt = base10x + 1;
  1178.       if (r != 0) {
  1179.         if ((r > 5) || ((r == 5) && (! roundedUp))) {
  1180.           roundedUp = true;
  1181.           mt++;
  1182.         } else {
  1183.           roundedUp = false;
  1184.         }
  1185.         int ft = decToFloat(n, xt, mt);
  1186.         if (ft != f) {
  1187.           if (roundedUp) {
  1188.             mt--;
  1189.           } else {
  1190.             mt++;
  1191.           }
  1192.           roundedUp ^= true;
  1193.           ft = decToFloat(n, xt, mt);
  1194.           if (ft != f) {
  1195.             break;
  1196.           }
  1197.         }
  1198.       }
  1199.       base10m = mt;
  1200.       base10x = xt;
  1201.     }
  1202.     
  1203.     // convert to string
  1204.     String s = Integer.toString(base10m);
  1205.     base10x += s.length() - 1;
  1206.     boolean scientific = ((base10x < -3) || (base10x >= 7));
  1207.     int dp; // index of decimal point in final string
  1208.     if (scientific) {
  1209.       dp = 1;
  1210.     } else {
  1211.       dp = base10x + 1;
  1212.       if (dp < 1) {
  1213.         sb.append('0');
  1214.       }
  1215.     }
  1216.     for (int i=0; i<dp; i++) {
  1217.       if (i < s.length()) {
  1218.         sb.append(s.charAt(i));
  1219.       } else {
  1220.         sb.append('0');
  1221.       }
  1222.     }
  1223.     sb.append('.');
  1224.     if (dp >= s.length()) {
  1225.       sb.append('0');
  1226.     } else {
  1227.       for (int i=dp; i<s.length(); i++) {
  1228.         if (i < 0) {
  1229.           sb.append('0');
  1230.         } else {
  1231.           sb.append(s.charAt(i));
  1232.         }
  1233.       }
  1234.     }
  1235.     if (scientific) {
  1236.       sb.append('E');
  1237.       sb.append(Integer.toString(base10x));
  1238.     }
  1239.     return sb.toString();
  1240.   }
  1241.   
  1242.   /////////////////////////////////////////////////////////////////////////////
  1243.   // Instance members
  1244.   /////////////////////////////////////////////////////////////////////////////
  1245.   private final int value;
  1246.   
  1247.   /////////////////////////////////////////////////////////////////////////////
  1248.   // Constructors
  1249.   /////////////////////////////////////////////////////////////////////////////
  1250.   
  1251.   /**
  1252.    * Constructs a newly-allocated <code>MicroFloat</code> object that represents 
  1253.    * the argument. 
  1254.    *
  1255.    * @param f the <code>float</code> value to be represented by the <code>MicroFloat</code>.
  1256.    */
  1257.   public MicroFloat(int f) {
  1258.     // canonicalize NaN values so that hashCode() and equals() can be simpler
  1259.     if (isNaN(f)) {
  1260.       f = NaN;
  1261.     }
  1262.     value = f;
  1263.   }
  1264.   
  1265.   /**
  1266.    * Constructs a newly-allocated <code>MicroFloat</code> object that represents 
  1267.    * the argument.
  1268.    *
  1269.    * @param s a <code>String</code> to be converted to a <code>MicroFloat</code>.
  1270.    * @throws NumberFormatException if the <code>String</code> does not contain a
  1271.    *         parsable number.
  1272.    * @see #parseFloat(String)
  1273.    */
  1274.   public MicroFloat(String s) {
  1275.     this(parseFloat(s));
  1276.   }
  1277.   
  1278.   /////////////////////////////////////////////////////////////////////////////
  1279.   // Instance methods
  1280.   /////////////////////////////////////////////////////////////////////////////
  1281.   
  1282.   /**
  1283.    * Returns the <code>float</code> value of this <code>MicroFloat</code>
  1284.    * object.
  1285.    */
  1286.   public int floatValue() {
  1287.     return value;
  1288.   }
  1289.   /**
  1290.    * Returns a String object representing this MicroFloat's value.
  1291.    * Equivalent to <code>toString(floatValue())</code>.
  1292.    *
  1293.    * @see #toString(int)
  1294.    */
  1295.   public String toString() {
  1296.     return toString(value);
  1297.   }
  1298.   /**
  1299.    * Returns a hash code for this <code>MicroFloat</code> object.
  1300.    * Equivalent to floatValue().
  1301.    */
  1302.   public int hashCode() {
  1303.     return value;
  1304.   }
  1305.   /**
  1306.    * Compares this object against the specified object.
  1307.    * Equivalent to <code>((obj instanceof MicroFloat) && (compare(((MicroFloat) obj).floatValue(), floatValue()) == 0))</code>
  1308.    * 
  1309.    * @see #compare(int, int)
  1310.    */
  1311.   public boolean equals(Object obj) {
  1312.     return ((obj instanceof MicroFloat)
  1313.             && (((MicroFloat) obj).value == value));
  1314.   }
  1315.   
  1316. }