/** * Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal. * * @return digits */ inline uint64_t __attr_always_inline___ ecma_errol0_dtoa (ecma_number_t val, /**< ecma number */ int32_t *num_of_digits_p, /**< [out] number of digits */ int32_t *exp_p) /**< [out] exponent */ { uint64_t digits = 0u; int32_t num_of_digits = 0; double power_of_10 = 1.0; int32_t exp = 1; /* normalize the midpoint */ ecma_high_prec_t mid; mid.value = val; mid.offset = 0.0; while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exp < 308)) { exp++; ecma_divide_high_prec_by_10 (&mid); power_of_10 /= 10.0; } while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exp > -307)) { exp--; ecma_multiply_high_prec_by_10 (&mid); power_of_10 *= 10.0; } ecma_high_prec_t high_bound, low_bound; high_bound.value = mid.value; high_bound.offset = mid.offset + (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); low_bound.value = mid.value; low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); ecma_normalize_high_prec_data (&high_bound); ecma_normalize_high_prec_data (&low_bound); /* normalized boundaries */ while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0))) { exp++; ecma_divide_high_prec_by_10 (&high_bound); ecma_divide_high_prec_by_10 (&low_bound); } while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0))) { exp--; ecma_multiply_high_prec_by_10 (&high_bound); ecma_multiply_high_prec_by_10 (&low_bound); } /* digit generation */ while (high_bound.value != 0.0 || high_bound.offset != 0.0) { uint8_t high_digit = (uint8_t) high_bound.value; if ((high_bound.value == high_digit) && (high_bound.offset < 0)) { high_digit = (uint8_t) (high_digit - 1u); } uint8_t low_digit = (uint8_t) low_bound.value; if ((low_bound.value == low_digit) && (low_bound.offset < 0)) { low_digit = (uint8_t) (low_digit - 1u); } if (low_digit != high_digit) { break; } digits *= 10; digits += (uint64_t) high_digit; num_of_digits++; high_bound.value -= high_digit; ecma_multiply_high_prec_by_10 (&high_bound); low_bound.value -= low_digit; ecma_multiply_high_prec_by_10 (&low_bound); } double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5; *num_of_digits_p = num_of_digits + 1; *exp_p = exp; digits *= 10; return digits + (uint64_t) mdig; } /* ecma_errol0_dtoa */
/** * Errol0 double to ASCII conversion, guaranteed correct but possibly not optimal. * * @return number of generated digits */ inline lit_utf8_size_t __attr_always_inline___ ecma_errol0_dtoa (double val, /**< ecma number */ lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */ int32_t *exp_p) /**< [out] exponent */ { double power_of_10 = 1.0; int32_t exp = 1; /* normalize the midpoint */ ecma_high_prec_t mid; mid.value = val; mid.offset = 0.0; while (((mid.value > 10.0) || ((mid.value == 10.0) && (mid.offset >= 0.0))) && (exp < 308)) { exp++; ecma_divide_high_prec_by_10 (&mid); power_of_10 /= 10.0; } while (((mid.value < 1.0) || ((mid.value == 1.0) && (mid.offset < 0.0))) && (exp > -307)) { exp--; ecma_multiply_high_prec_by_10 (&mid); power_of_10 *= 10.0; } ecma_high_prec_t high_bound, low_bound; high_bound.value = mid.value; high_bound.offset = mid.offset; if (ECMA_NEXT_FLOAT (val) != INFINITY) { high_bound.offset += (ECMA_NEXT_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); } low_bound.value = mid.value; low_bound.offset = mid.offset + (ECMA_PREV_FLOAT (val) - val) * power_of_10 / (2.0 + ERROL0_EPSILON); ecma_normalize_high_prec_data (&high_bound); ecma_normalize_high_prec_data (&low_bound); /* normalized boundaries */ while (high_bound.value > 10.0 || (high_bound.value == 10.0 && (high_bound.offset >= 0.0))) { exp++; ecma_divide_high_prec_by_10 (&high_bound); ecma_divide_high_prec_by_10 (&low_bound); } while (high_bound.value < 1.0 || (high_bound.value == 1.0 && (high_bound.offset < 0.0))) { exp--; ecma_multiply_high_prec_by_10 (&high_bound); ecma_multiply_high_prec_by_10 (&low_bound); } /* digit generation */ lit_utf8_byte_t *dst_p = buffer_p; while (high_bound.value != 0.0 || high_bound.offset != 0.0) { uint8_t high_digit = (uint8_t) high_bound.value; if ((high_bound.value == high_digit) && (high_bound.offset < 0)) { high_digit = (uint8_t) (high_digit - 1u); } uint8_t low_digit = (uint8_t) low_bound.value; if ((low_bound.value == low_digit) && (low_bound.offset < 0)) { low_digit = (uint8_t) (low_digit - 1u); } if (low_digit != high_digit) { break; } *dst_p++ = (lit_utf8_byte_t) ('0' + high_digit); high_bound.value -= high_digit; ecma_multiply_high_prec_by_10 (&high_bound); low_bound.value -= low_digit; ecma_multiply_high_prec_by_10 (&low_bound); } double mdig = (high_bound.value + low_bound.value) / 2.0 + 0.5; *dst_p++ = (lit_utf8_byte_t) ('0' + (uint8_t) mdig); *exp_p = exp; return (lit_utf8_size_t) (dst_p - buffer_p); } /* ecma_errol0_dtoa */