Logo Search packages:      
Sourcecode: yasm version File versions  Download package

yasm_floatnum* yasm_floatnum_create ( const char *  str  ) 

Create a new floatnum from a decimal string. The input string must be in standard C representation ([+-]123.456e[-+]789).

Parameters:
str floating point decimal string
Returns:
Newly allocated floatnum.

Definition at line 306 of file floatnum.c.

References yasm_xmalloc.

{
    yasm_floatnum *flt;
    int dec_exponent, dec_exp_add;  /* decimal (powers of 10) exponent */
    int POT_index;
    wordptr operand[2];
    int sig_digits;
    int decimal_pt;
    boolean carry;

    flt = yasm_xmalloc(sizeof(yasm_floatnum));

    flt->mantissa = BitVector_Create(MANT_BITS, TRUE);

    /* allocate and initialize calculation variables */
    operand[0] = BitVector_Create(MANT_BITS, TRUE);
    operand[1] = BitVector_Create(MANT_BITS, TRUE);
    dec_exponent = 0;
    sig_digits = 0;
    decimal_pt = 1;

    /* set initial flags to 0 */
    flt->flags = 0;

    /* check for + or - character and skip */
    if (*str == '-') {
      flt->sign = 1;
      str++;
    } else if (*str == '+') {
      flt->sign = 0;
      str++;
    } else
      flt->sign = 0;

    /* eliminate any leading zeros (which do not count as significant digits) */
    while (*str == '0')
      str++;

    /* When we reach the end of the leading zeros, first check for a decimal
     * point.  If the number is of the form "0---0.0000" we need to get rid
     * of the zeros after the decimal point and not count them as significant
     * digits.
     */
    if (*str == '.') {
      str++;
      while (*str == '0') {
          str++;
          dec_exponent--;
      }
    } else {
      /* The number is of the form "yyy.xxxx" (where y <> 0). */
      while (isdigit(*str)) {
          /* See if we've processed more than the max significant digits: */
          if (sig_digits < MANT_SIGDIGITS) {
            /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
            BitVector_shift_left(flt->mantissa, 0);
            BitVector_Copy(operand[0], flt->mantissa);
            BitVector_Move_Left(flt->mantissa, 2);
            carry = 0;
            BitVector_add(operand[1], operand[0], flt->mantissa, &carry);

            /* Add in current digit */
            BitVector_Empty(operand[0]);
            BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
            carry = 0;
            BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
          } else {
            /* Can't integrate more digits with mantissa, so instead just
             * raise by a power of ten.
             */
            dec_exponent++;
          }
          sig_digits++;
          str++;
      }

      if (*str == '.')
          str++;
      else
          decimal_pt = 0;
    }

    if (decimal_pt) {
      /* Process the digits to the right of the decimal point. */
      while (isdigit(*str)) {
          /* See if we've processed more than 19 significant digits: */
          if (sig_digits < 19) {
            /* Raise by a power of ten */
            dec_exponent--;

            /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
            BitVector_shift_left(flt->mantissa, 0);
            BitVector_Copy(operand[0], flt->mantissa);
            BitVector_Move_Left(flt->mantissa, 2);
            carry = 0;
            BitVector_add(operand[1], operand[0], flt->mantissa, &carry);

            /* Add in current digit */
            BitVector_Empty(operand[0]);
            BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
            carry = 0;
            BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
          }
          sig_digits++;
          str++;
      }
    }

    if (*str == 'e' || *str == 'E') {
      str++;
      /* We just saw the "E" character, now read in the exponent value and
       * add it into dec_exponent.
       */
      dec_exp_add = 0;
      sscanf(str, "%d", &dec_exp_add);
      dec_exponent += dec_exp_add;
    }

    /* Free calculation variables. */
    BitVector_Destroy(operand[1]);
    BitVector_Destroy(operand[0]);

    /* Normalize the number, checking for 0 first. */
    if (BitVector_is_empty(flt->mantissa)) {
      /* Mantissa is 0, zero exponent too. */
      flt->exponent = 0;
      /* Set zero flag so output functions don't see 0 value as underflow. */
      flt->flags |= FLAG_ISZERO;
      /* Return 0 value. */
      return flt;
    }
    /* Exponent if already norm. */
    flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
    floatnum_normalize(flt);

    /* The number is normalized.  Now multiply by 10 the number of times
     * specified in DecExponent.  This uses the power of ten tables to speed
     * up this operation (and make it more accurate).
     */
    if (dec_exponent > 0) {
      POT_index = 0;
      /* Until we hit 1.0 or finish exponent or overflow */
      while ((POT_index < 14) && (dec_exponent != 0) &&
             (flt->exponent != EXP_INF)) {
          /* Find the first power of ten in the table which is just less than
           * the exponent.
           */
          while (dec_exponent < POT_TableP[POT_index].dec_exponent)
            POT_index++;

          if (POT_index < 14) {
            /* Subtract out what we're multiplying in from exponent */
            dec_exponent -= POT_TableP[POT_index].dec_exponent;

            /* Multiply by current power of 10 */
            floatnum_mul(flt, &POT_TableP[POT_index].f);
          }
      }
    } else if (dec_exponent < 0) {
      POT_index = 0;
      /* Until we hit 1.0 or finish exponent or underflow */
      while ((POT_index < 14) && (dec_exponent != 0) &&
             (flt->exponent != EXP_ZERO)) {
          /* Find the first power of ten in the table which is just less than
           * the exponent.
           */
          while (dec_exponent > POT_TableN[POT_index].dec_exponent)
            POT_index++;

          if (POT_index < 14) {
            /* Subtract out what we're multiplying in from exponent */
            dec_exponent -= POT_TableN[POT_index].dec_exponent;

            /* Multiply by current power of 10 */
            floatnum_mul(flt, &POT_TableN[POT_index].f);
          }
      }
    }

    /* Round the result. (Don't round underflow or overflow). */
    if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO))
      BitVector_increment(flt->mantissa);

    return flt;
}


Generated by  Doxygen 1.6.0   Back to index