code: public static float ulp(float f) {
          int exp = getExponent(f);
  
          switch(exp) {
          case FloatConsts.MAX_EXPONENT+1:        // NaN or infinity
              return Math.abs(f);
  
          case FloatConsts.MIN_EXPONENT-1:        // zero or subnormal
              return FloatConsts.MIN_VALUE;
  
          default:
              assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT;
  
              // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
              exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1);
              if (exp >= FloatConsts.MIN_EXPONENT) {
                  return powerOfTwoF(exp);
              }
              else {
                  // return a subnormal result; left shift integer
                  // representation of FloatConsts.MIN_VALUE appropriate
                  // number of positions
                  return Float.intBitsToFloat(1 <<
                  (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
              }
          }
       }
docs: Returns the size of an ulp of the argument.  An ulp of a
  {@code float} value is the positive distance between this
  floating-point value and the {@code float} value next
  larger in magnitude.  Note that for non-NaN <i>x</i>,
  <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>.
  
  <p>Special Cases:
  <ul>
  <li> If the argument is NaN, then the result is NaN.
  <li> If the argument is positive or negative infinity, then the
  result is positive infinity.
  <li> If the argument is positive or negative zero, then the result is
  {@code Float.MIN_VALUE}.
  <li> If the argument is &plusmn;{@code Float.MAX_VALUE}, then
  the result is equal to 2<sup>104</sup>.
  </ul>
  
  @param f the floating-point value whose ulp is to be returned
  @return the size of an ulp of the argument
  @author Joseph D. Darcy
  @since 1.5