⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 microfloat.java

📁 This is a Java library for performing floating-point calculations on small devices such as mobile p
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
  /**
   * Mimics 
   * <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html#min(float, float)">Math.min(float, float)</a>.
   */
  public static int min(int f1, int f2) {
    if (isNaN(f1) || isNaN(f2)) {
      return NaN;
    }
    return ((cmp(f1, f2) > 0) ? f2 : f1);
  }

  private static int cmp(int f1, int f2) {
    if (f1 < 0) {
      if (f2 < 0) {
        return f2 - f1;
      } else {
        return -1;
      }
    } else if (f2 < 0) {
      return 1;
    } else {
      return f1 - f2;
    }
  }


  /////////////////////////////////////////////////////////////////////////////
  // Type conversion
  /////////////////////////////////////////////////////////////////////////////

  /** 
   * Convert the given <code>int</code> to a <code>float</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
   * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
   * will not result in a loss of magnitude, but might result in a loss of
   * precision.
   *
   * @param x the <code>int</code> to be converted
   * @return the <code>float</code> representation of the argument
   */
  public static int intToFloat(int x) {
    if (x < 0) {
      return pack(true, 0, -x);
    }
    return pack(false, 0, x);
  }
  
  /** 
   * Convert the given <code>long</code> to a <code>float</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
   * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
   * will not result in a loss of magnitude, but might result in a loss of
   * precision.
   *
   * @param x the <code>long</code> to be converted
   * @return the <code>float</code> representation of the argument
   */
  public static int longToFloat(long x) {
    if (x < 0) {
      return pack(true, 0, -x);
    }
    return pack(false, 0, x);
  }

  /** 
   * Convert the given <code>double</code> to a <code>float</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
   * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
   * may result in a loss of magnitude and/or precision.
   *
   * @param d the <code>double</code> to be converted
   * @return the <code>float</code> representation of the argument
   */
  public static int doubleToFloat(long d) {
    if (MicroDouble.isNaN(d)) {
      return NaN;
    }
    boolean n = MicroDouble.unpackSign(d);
    if (MicroDouble.isZero(d)) {
      return (n ? NEGATIVE_ZERO : ZERO);
    } else if (MicroDouble.isInfinite(d)) {
      return (n ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
    }
    int x = MicroDouble.unpackExponent(d);
    long m = MicroDouble.unpackMantissa(d);
    return pack(n, x, m);
  }

  /** 
   * Convert the given <code>float</code> to a <code>byte</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
   * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
   * may result in a loss of magnitude and/or precision.
   * <p>
   * Note that this is a non-intuitive conversion.  If the argument is outside
   * of the range of the byte type, the result is basically meaningless.
   *
   * @param f the <code>float</code> to be converted
   * @return the <code>byte</code> representation of the argument
   */
  public static byte byteValue(int f) {
    long x = intValue(f);
    return (byte) x;
  }

  /** 
   * Convert the given <code>float</code> to a <code>short</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
   * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
   * may result in a loss of magnitude and/or precision.
   * <p>
   * Note that this is a non-intuitive conversion.  If the argument is outside
   * of the range of the short type, the result is basically meaningless.
   *
   * @param f the <code>float</code> to be converted
   * @return the <code>short</code> representation of the argument
   */
  public static short shortValue(int f) {
    long x = intValue(f);
    return (short) x;
  }

  /** 
   * Convert the given <code>float</code> to an <code>int</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
   * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
   * may result in a loss of magnitude and/or precision.
   *
   * @param f the <code>float</code> to be converted
   * @return the <code>int</code> representation of the argument
   */
  public static int intValue(int f) {
    long x = longValue(f);
    if (x >= Integer.MAX_VALUE) {
      return Integer.MAX_VALUE;
    } else if (x <= Integer.MIN_VALUE) {
      return Integer.MIN_VALUE;
    }
    return (int) x;
  }
  
  /** 
   * Convert the given <code>float</code> to a <code>long</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25363">section
   * 5.1.3 of the JLS</a>.  This is a narrowing primitive conversion which 
   * may result in a loss of magnitude and/or precision.
   *
   * @param f the <code>float</code> to be converted
   * @return the <code>long</code> representation of the argument
   */
  public static long longValue(int f) {
    if (isNaN(f)) {
      return 0;
    }
    boolean n = unpackSign(f);
    int x = unpackExponent(f);
    long m = unpackMantissa(f);
    if (x > 0) {
      if ((x >= 63) || ((m >> (63 - x)) != 0))  {
        return (n ? Long.MIN_VALUE : Long.MAX_VALUE);
      }
      m <<= x;
    } else if (x <= -24) {
      return 0;
    } else {
      m >>>= -x;
    }
    return (n ? -m : m);
  }

  /** 
   * Convert the given <code>float</code> to a <code>double</code> as would happen
   * in a casting operation specified by 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#25214">section
   * 5.1.2 of the JLS</a>.  This is a widening primitive conversion which 
   * will result in neither a loss of magnitude nor precision.
   *
   * @param f the <code>float</code> to be converted
   * @return the <code>double</code> representation of the argument
   */
  public static long doubleValue(int f) {
    return MicroDouble.floatToDouble(f);
  }
  

  /////////////////////////////////////////////////////////////////////////////
  // Basic arithmetic
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Returns the sum of the two <code>float</code> arguments according to 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510">section
   * 15.18.2 of the JLS</a>.
   * <p>
   * This method takes the place of the binary <code>+</code> operator.
   *
   * @param   f1   the first <code>float</code> value to be summed.
   * @param   f2   the second <code>float</code> value to be summed.
   * @return  the sum of the two arguments
   */
  public static int add(int f1, int f2) {
    if (isNaN(f1) || isNaN(f2)) {
      return NaN;
    }
    
    boolean n1 = unpackSign(f1);
    boolean n2 = unpackSign(f2);
    
    // special handling of infinity
    boolean i1 = isInfinite(f1);
    boolean i2 = isInfinite(f2);
    if (i1 || i2) {
      if (i1 && i2) {
        if (n1 != n2) {
          // infinites of opposite sign -> NaN
          return NaN;
        } else {
          // infinites of same sign -> infinity the same sign
          return f1;
        }
      } else if (i1) {
        return f1; // infinite + finite = infinite
      } else {
        return f2; // finite + infinite = infinite
      }
    }
    
    // special handling of zero
    boolean z1 = isZero(f1);
    boolean z2 = isZero(f2);
    if (z1 || z2) {
      if (z1 && z2) {
        if (n1 != n2) {
          // zeros of opposite sign -> positive zero
          return ZERO;
        } else {
          return f1; // zeros of same sign -> zero of the same sign
        }
      } else if (z1) {
        return f2; // zero + nonzero = nonzero
      } else {
        return f1; // nonzero + zero = nonzero
      }
    }
    
    // unpack, and add 3 guard digits
    int m1 = unpackMantissa(f1) << 3;
    int x1 = unpackExponent(f1) - 3;
    int m2 = unpackMantissa(f2) << 3;
    int x2 = unpackExponent(f2) - 3;

    // make exponents equal
    int dx = x1 - x2;
    if (dx > 0) {
      m2 = BitUtils.stickyRightShift(m2, dx);
      x2 = x1;
    } else if (dx < 0) {
      m1 = BitUtils.stickyRightShift(m1, -dx);
      x1 = x2;
    }

    // if the signs are different, negate the smaller mantissa and choose
    // the sign of the larger
    if (n1 ^ n2) { 
      if (m1 > m2) {
        m2 = -m2;
      } else {
        m1 = -m1;
        n1 = n2;
      }
    }
    
    // add (or subtract) mantissas
    m1 += m2;

    // pack result, and handle special case of zero (which always returns +0.0) 
    int f = pack(n1, x1, m1);
    if (f == NEGATIVE_ZERO) {
      return ZERO;
    }
    return f;
  }

  /**
   * Returns the difference of the two <code>float</code> arguments according to 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510">section
   * 15.18.2 of the JLS</a>.
   * <p>
   * This method takes the place of the binary <code>-</code> operator.
   *
   * @param   f1   the first <code>float</code> value 
   * @param   f2   the second <code>float</code> value
   * @return  the difference of the two arguments
   */
  public static int sub(int f1, int f2) {
    return add(f1, negate(f2));
  }

  /**
   * Returns the product of the two <code>float</code> arguments according to 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5036">section
   * 15.17.1 of the JLS</a>.
   * <p>
   * This method takes the place of the <code>*</code> operator.
   *
   * @param   f1   the first <code>float</code> value
   * @param   f2   the second <code>float</code> value
   * @return  the product of the two arguments
   */
  public static int mul(int f1, int f2) {
    if (isNaN(f1) || isNaN(f2)) {
      return NaN;
    }

    boolean negative = unpackSign(f1) ^ unpackSign(f2);
    
    // special handling of infinity
    if (isInfinite(f1) || isInfinite(f2)) {
      if (isZero(f1) || isZero(f2)) {
        return NaN;
      } else {
        return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
      }
    }
    
    // unpack
    int m1 = unpackMantissa(f1);
    int x1 = unpackExponent(f1);
    int m2 = unpackMantissa(f2);
    int x2 = unpackExponent(f2);
    
    // compute the resultant exponent
    x1 += x2;
    
    // compute the resultant mantissa using integer multiplication
    long m = ((long) m1) * ((long) m2);
    
    // round and pack the result
    return pack(negative, x1, m);
  }

  /**
   * Returns the quotient of the two <code>float</code> arguments according to 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5047">section
   * 15.17.2 of the JLS</a>.
   * <p>
   * This method takes the place of the <code>/</code> operator.
   *
   * @param   f1   the <code>float</code> dividend 
   * @param   f2   the <code>float</code> divisor
   * @return  the quotient of the two arguments
   */
  public static int div(int f1, int f2) {
    if (isNaN(f1) || isNaN(f2)) {
      return NaN;
    }

    boolean negative = unpackSign(f1) ^ unpackSign(f2);
    
    // special handling of infinity
    boolean n1 = isInfinite(f1);
    boolean n2 = isInfinite(f2);
    if (n1 || n2) {
      if (n1 && n2) {
        return NaN;
      } else if (n1) {
        return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
      } else {
        return (negative ? NEGATIVE_ZERO : ZERO);
      }
    }
    // neither value is infinite
    
    // special handling of zero
    n1 = isZero(f1);
    n2 = isZero(f2);
    if (n1 || n2) {
      if (n1 && n2) {
        return NaN;
      } else if (n1) {
        return (negative ? NEGATIVE_ZERO : ZERO);
      } else {
        return (negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY);
      }
    }
    // neither value is zero
    
    // unpack
    int m1 = unpackMantissa(f1);
    int x1 = unpackExponent(f1);
    int m2 = unpackMantissa(f2);
    int x2 = unpackExponent(f2);

    // shift the dividend to the left to increase precision, then do an integer
    // divide
    int s = BitUtils.countLeadingZeros(m1) + 22;
    long m3 = ((long) m1) << s;
    int x = x1 - x2 - s;
    long m = m3 / m2;
    boolean r = ((m * m2) != m3);

    // put a non-zero fraction into the sticky bit
    if (r) {
      m |= 1; 
    }
    return pack(negative, x, m);
  }

  /**
   * Returns the remainder of the two <code>float</code> arguments according to 
   * <a href="http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#24956">section
   * 15.17.3 of the JLS</a>.
   * <p>
   * This method takes the place of the <code>%</code> operator.
   *
   * @param   f1   the <code>float</code> dividend 
   * @param   f2   the <code>float</code> divisor
   * @return  the remainder of the two arguments
   */
  public static int mod(int f1, int f2) {
    if (isNaN(f1) || isNaN(f2) || isInfinite(f1) || isZero(f2)) {
      return NaN;
    } else if (isZero(f1) || isInfinite(f2)) {
      return f1;
    }
    
    // unpack
    int x1 = unpackExponent(f1);
    int x2 = unpackExponent(f2);
    if (x1 < x2) {
      return f1;
    }
    boolean n = unpackSign(f1);
    int m1 = unpackMantissa(f1);
    int m2 = unpackMantissa(f2);
    if (x1 == x2) {
      m1 %= m2;
    } else {
      // reduce m1 by left shifting and modding until the exponents x1 and x2 are 
      // equal
      while (x1 != x2) {
        int s = Math.min(39, x1 - x2);
        x1 -= s;
        m1 = (int) ((((long) m1) << s) % m2);
      }
    }
    return pack(n, x1, m1);
  }


  /////////////////////////////////////////////////////////////////////////////
  // Rounding
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Returns the <code>float</code> of greatest magnitude (furthest from zero)
   * that is equal to a mathematical integer and which has a mignitude not
   * greater than the argument's magnitude.  Special cases:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -