1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include <math.h>
17425bb815Sopenharmony_ci
18425bb815Sopenharmony_ci#include "ecma-globals.h"
19425bb815Sopenharmony_ci#include "ecma-helpers.h"
20425bb815Sopenharmony_ci#include "jrt-libc-includes.h"
21425bb815Sopenharmony_ci#include "lit-char-helpers.h"
22425bb815Sopenharmony_ci#include "lit-magic-strings.h"
23425bb815Sopenharmony_ci
24425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
25425bb815Sopenharmony_ci * @{
26425bb815Sopenharmony_ci *
27425bb815Sopenharmony_ci * \addtogroup ecmahelpers Helpers for operations with ECMA data types
28425bb815Sopenharmony_ci * @{
29425bb815Sopenharmony_ci */
30425bb815Sopenharmony_ci
31425bb815Sopenharmony_ci#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
32425bb815Sopenharmony_ci
33425bb815Sopenharmony_ci/**
34425bb815Sopenharmony_ci * \addtogroup ecmahelpersbigintegers Helpers for operations intermediate 128-bit integers
35425bb815Sopenharmony_ci * @{
36425bb815Sopenharmony_ci */
37425bb815Sopenharmony_ci
38425bb815Sopenharmony_ci/**
39425bb815Sopenharmony_ci * 128-bit integer type
40425bb815Sopenharmony_ci */
41425bb815Sopenharmony_citypedef struct
42425bb815Sopenharmony_ci{
43425bb815Sopenharmony_ci  uint64_t lo; /**< low 64 bits */
44425bb815Sopenharmony_ci  uint64_t hi; /**< high 64 bits */
45425bb815Sopenharmony_ci} ecma_uint128_t;
46425bb815Sopenharmony_ci
47425bb815Sopenharmony_ci/**
48425bb815Sopenharmony_ci * Round high part of 128-bit integer to uint64_t
49425bb815Sopenharmony_ci *
50425bb815Sopenharmony_ci * @return rounded high to uint64_t
51425bb815Sopenharmony_ci */
52425bb815Sopenharmony_cistatic uint64_t
53425bb815Sopenharmony_ciecma_round_high_to_uint64 (ecma_uint128_t *num_p)
54425bb815Sopenharmony_ci{
55425bb815Sopenharmony_ci  uint64_t masked_lo = num_p->lo & ~(1ULL << 63u);
56425bb815Sopenharmony_ci  uint64_t masked_hi = num_p->hi & 0x1;
57425bb815Sopenharmony_ci
58425bb815Sopenharmony_ci  if ((num_p->lo >> 63u != 0)
59425bb815Sopenharmony_ci      && (masked_lo > 0 || masked_hi != 0))
60425bb815Sopenharmony_ci  {
61425bb815Sopenharmony_ci    return (num_p->hi + 1);
62425bb815Sopenharmony_ci  }
63425bb815Sopenharmony_ci  return num_p->hi;
64425bb815Sopenharmony_ci} /* ecma_round_high_to_uint64 */
65425bb815Sopenharmony_ci
66425bb815Sopenharmony_ci/**
67425bb815Sopenharmony_ci * Check if 128-bit integer is zero
68425bb815Sopenharmony_ci */
69425bb815Sopenharmony_ci#define ECMA_UINT128_IS_ZERO(name) \
70425bb815Sopenharmony_ci  (name.hi == 0 && name.lo == 0)
71425bb815Sopenharmony_ci
72425bb815Sopenharmony_ci/**
73425bb815Sopenharmony_ci * Left shift 128-bit integer by max 63 bits
74425bb815Sopenharmony_ci */
75425bb815Sopenharmony_ci#define ECMA_UINT128_LEFT_SHIFT_MAX63(name, shift) \
76425bb815Sopenharmony_ci{ \
77425bb815Sopenharmony_ci  name.hi = (name.hi << (shift)) | (name.lo >> (64 - (shift))); \
78425bb815Sopenharmony_ci  name.lo <<= (shift); \
79425bb815Sopenharmony_ci}
80425bb815Sopenharmony_ci
81425bb815Sopenharmony_ci/**
82425bb815Sopenharmony_ci * Right shift 128-bit integer by max 63 bits
83425bb815Sopenharmony_ci */
84425bb815Sopenharmony_ci#define ECMA_UINT128_RIGHT_SHIFT_MAX63(name, shift) \
85425bb815Sopenharmony_ci{ \
86425bb815Sopenharmony_ci  name.lo = (name.lo >> (shift)) | (name.hi << (64 - (shift))); \
87425bb815Sopenharmony_ci  name.hi >>= (shift); \
88425bb815Sopenharmony_ci}
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_ci/**
91425bb815Sopenharmony_ci * Add 128-bit integer
92425bb815Sopenharmony_ci */
93425bb815Sopenharmony_ci#define ECMA_UINT128_ADD(name_add_to, name_to_add) \
94425bb815Sopenharmony_ci{ \
95425bb815Sopenharmony_ci  name_add_to.hi += name_to_add.hi; \
96425bb815Sopenharmony_ci  name_add_to.lo += name_to_add.lo; \
97425bb815Sopenharmony_ci  if (name_add_to.lo < name_to_add.lo) \
98425bb815Sopenharmony_ci  { \
99425bb815Sopenharmony_ci    name_add_to.hi++; \
100425bb815Sopenharmony_ci  } \
101425bb815Sopenharmony_ci}
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci/**
104425bb815Sopenharmony_ci * Multiply 128-bit integer by 10
105425bb815Sopenharmony_ci */
106425bb815Sopenharmony_ci#define ECMA_UINT128_MUL10(name) \
107425bb815Sopenharmony_ci{ \
108425bb815Sopenharmony_ci  ECMA_UINT128_LEFT_SHIFT_MAX63 (name, 1u); \
109425bb815Sopenharmony_ci  \
110425bb815Sopenharmony_ci  ecma_uint128_t name ## _tmp = name; \
111425bb815Sopenharmony_ci  \
112425bb815Sopenharmony_ci  ECMA_UINT128_LEFT_SHIFT_MAX63 (name ## _tmp, 2u); \
113425bb815Sopenharmony_ci  \
114425bb815Sopenharmony_ci  ECMA_UINT128_ADD (name, name ## _tmp); \
115425bb815Sopenharmony_ci}
116425bb815Sopenharmony_ci
117425bb815Sopenharmony_ci/**
118425bb815Sopenharmony_ci * Divide 128-bit integer by 10
119425bb815Sopenharmony_ci *
120425bb815Sopenharmony_ci * N = N3 *2^96  + N2 *2^64  + N1 *2^32  + N0 *2^0     // 128-bit dividend
121425bb815Sopenharmony_ci * T = T3 *2^-32 + T2 *2^-64 + T1 *2^-96 + T0 *2^-128  // 128-bit divisor reciprocal, 1/10 * 2^-128
122425bb815Sopenharmony_ci *
123425bb815Sopenharmony_ci * N * T    = N3*T3 *2^64 + N2*T3 *2^32 + N1*T3 *2^0 + N0*T3 *2^-32
124425bb815Sopenharmony_ci *          +               N3*T2 *2^32 + N2*T2 *2^0 + N1*T2 *2^-32 + N0*T2 *2^-64
125425bb815Sopenharmony_ci *          +                             N3*T1 *2^0 + N2*T1 *2^-32 + N1*T1 *2^-64 + N0*T1 *2^-96
126425bb815Sopenharmony_ci *          +                                          N3*T0 *2^-32 + N2*T0 *2^-64 + N1*T0 *2^-96 + N0*T0 *2^-128
127425bb815Sopenharmony_ci *
128425bb815Sopenharmony_ci *  Q3=carry  Q2=^+carry    Q1=^+carry    Q0=^+carry   fraction=^...
129425bb815Sopenharmony_ci *
130425bb815Sopenharmony_ci * Q = Q3 *2^96  + Q2 *2^64  + Q1 *2^32  + Q0 *2^0     // 128-bit quotient
131425bb815Sopenharmony_ci */
132425bb815Sopenharmony_ci#define ECMA_UINT128_DIV10(name) \
133425bb815Sopenharmony_ci{ \
134425bb815Sopenharmony_ci  /* estimation of reciprocal of 10, 128 bits right of the binary point (T1 == T2) */ \
135425bb815Sopenharmony_ci  const uint64_t tenth_l = 0x9999999aul; \
136425bb815Sopenharmony_ci  const uint64_t tenth_m = 0x99999999ul; \
137425bb815Sopenharmony_ci  const uint64_t tenth_h = 0x19999999ul; \
138425bb815Sopenharmony_ci  \
139425bb815Sopenharmony_ci  uint64_t l0 = ((uint32_t) name.lo) * tenth_l; \
140425bb815Sopenharmony_ci  uint64_t l1 = (name.lo >> 32u) * tenth_l; \
141425bb815Sopenharmony_ci  uint64_t l2 = ((uint32_t) name.hi) * tenth_l; \
142425bb815Sopenharmony_ci  uint64_t l3 = (name.hi >> 32u) * tenth_l; \
143425bb815Sopenharmony_ci  uint64_t m0 = ((uint32_t) name.lo) * tenth_m; \
144425bb815Sopenharmony_ci  uint64_t m1 = (name.lo >> 32u) * tenth_m; \
145425bb815Sopenharmony_ci  uint64_t m2 = ((uint32_t) name.hi) * tenth_m; \
146425bb815Sopenharmony_ci  uint64_t m3 = (name.hi >> 32u) * tenth_m; \
147425bb815Sopenharmony_ci  uint64_t h0 = ((uint32_t) name.lo) * tenth_h; \
148425bb815Sopenharmony_ci  uint64_t h1 = (name.lo >> 32u) * tenth_h; \
149425bb815Sopenharmony_ci  uint64_t h2 = ((uint32_t) name.hi) * tenth_h; \
150425bb815Sopenharmony_ci  uint64_t h3 = (name.hi >> 32u) * tenth_h; \
151425bb815Sopenharmony_ci  \
152425bb815Sopenharmony_ci  uint64_t q0 = l0 >> 32u; \
153425bb815Sopenharmony_ci  q0 += (uint32_t) l1; \
154425bb815Sopenharmony_ci  q0 += (uint32_t) m0; \
155425bb815Sopenharmony_ci  \
156425bb815Sopenharmony_ci  q0 >>= 32u; \
157425bb815Sopenharmony_ci  q0 += l1 >> 32u; \
158425bb815Sopenharmony_ci  q0 += m0 >> 32u; \
159425bb815Sopenharmony_ci  q0 += (uint32_t) l2; \
160425bb815Sopenharmony_ci  q0 += (uint32_t) m1; \
161425bb815Sopenharmony_ci  q0 += (uint32_t) m0; \
162425bb815Sopenharmony_ci  \
163425bb815Sopenharmony_ci  q0 >>= 32u; \
164425bb815Sopenharmony_ci  q0 += l2 >> 32u; \
165425bb815Sopenharmony_ci  q0 += m1 >> 32u; \
166425bb815Sopenharmony_ci  q0 += m0 >> 32u; \
167425bb815Sopenharmony_ci  q0 += (uint32_t) l3; \
168425bb815Sopenharmony_ci  q0 += (uint32_t) m2; \
169425bb815Sopenharmony_ci  q0 += (uint32_t) m1; \
170425bb815Sopenharmony_ci  q0 += (uint32_t) h0; \
171425bb815Sopenharmony_ci  \
172425bb815Sopenharmony_ci  q0 >>=32u; \
173425bb815Sopenharmony_ci  q0 += l3 >> 32u; \
174425bb815Sopenharmony_ci  q0 += m2 >> 32u; \
175425bb815Sopenharmony_ci  q0 += m1 >> 32u; \
176425bb815Sopenharmony_ci  q0 += h0 >> 32u; \
177425bb815Sopenharmony_ci  q0 += (uint32_t) m3; \
178425bb815Sopenharmony_ci  q0 += (uint32_t) m2; \
179425bb815Sopenharmony_ci  q0 += (uint32_t) h1; \
180425bb815Sopenharmony_ci  \
181425bb815Sopenharmony_ci  uint64_t q1 = q0 >> 32u; \
182425bb815Sopenharmony_ci  q1 += m3 >> 32u; \
183425bb815Sopenharmony_ci  q1 += m2 >> 32u; \
184425bb815Sopenharmony_ci  q1 += h1 >> 32u; \
185425bb815Sopenharmony_ci  q1 += (uint32_t) m3; \
186425bb815Sopenharmony_ci  q1 += (uint32_t) h2; \
187425bb815Sopenharmony_ci  \
188425bb815Sopenharmony_ci  uint64_t q32 = q1 >> 32u; \
189425bb815Sopenharmony_ci  q32 += m3 >> 32u; \
190425bb815Sopenharmony_ci  q32 += h2 >> 32u; \
191425bb815Sopenharmony_ci  q32 += h3; \
192425bb815Sopenharmony_ci  \
193425bb815Sopenharmony_ci  name.lo = (q1 << 32u) | ((uint32_t) q0); \
194425bb815Sopenharmony_ci  name.hi = q32; \
195425bb815Sopenharmony_ci}
196425bb815Sopenharmony_ci
197425bb815Sopenharmony_ci#if defined (__GNUC__) || defined (__clang__)
198425bb815Sopenharmony_ci
199425bb815Sopenharmony_ci/**
200425bb815Sopenharmony_ci * Count leading zeros in the topmost 64 bits of a 128-bit integer.
201425bb815Sopenharmony_ci */
202425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX63(name) \
203425bb815Sopenharmony_ci  __builtin_clzll (name.hi)
204425bb815Sopenharmony_ci
205425bb815Sopenharmony_ci/**
206425bb815Sopenharmony_ci * Count leading zeros in the topmost 4 bits of a 128-bit integer.
207425bb815Sopenharmony_ci */
208425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX4(name) \
209425bb815Sopenharmony_ci  __builtin_clzll (name.hi)
210425bb815Sopenharmony_ci
211425bb815Sopenharmony_ci#else /* !__GNUC__ && !__clang__ */
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci/**
214425bb815Sopenharmony_ci * Count leading zeros in a 64-bit integer. The behaviour is undefined for 0.
215425bb815Sopenharmony_ci *
216425bb815Sopenharmony_ci * @return number of leading zeros.
217425bb815Sopenharmony_ci */
218425bb815Sopenharmony_cistatic inline int JERRY_ATTR_ALWAYS_INLINE
219425bb815Sopenharmony_ciecma_uint64_clz (uint64_t n) /**< integer to count leading zeros in */
220425bb815Sopenharmony_ci{
221425bb815Sopenharmony_ci  JERRY_ASSERT (n != 0);
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  int cnt = 0;
224425bb815Sopenharmony_ci  uint64_t one = 0x8000000000000000ull;
225425bb815Sopenharmony_ci  while ((n & one) == 0)
226425bb815Sopenharmony_ci  {
227425bb815Sopenharmony_ci    cnt++;
228425bb815Sopenharmony_ci    one >>= 1;
229425bb815Sopenharmony_ci  }
230425bb815Sopenharmony_ci  return cnt;
231425bb815Sopenharmony_ci} /* ecma_uint64_clz */
232425bb815Sopenharmony_ci
233425bb815Sopenharmony_ci/**
234425bb815Sopenharmony_ci * Number of leading zeros in 4-bit integers.
235425bb815Sopenharmony_ci */
236425bb815Sopenharmony_cistatic const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
237425bb815Sopenharmony_ci
238425bb815Sopenharmony_ci/**
239425bb815Sopenharmony_ci * Count leading zeros in the topmost 64 bits of a 128-bit integer.
240425bb815Sopenharmony_ci */
241425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX63(name) \
242425bb815Sopenharmony_ci  ecma_uint64_clz (name.hi)
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci/**
245425bb815Sopenharmony_ci * Count leading zeros in the topmost 4 bits of a 128-bit integer.
246425bb815Sopenharmony_ci */
247425bb815Sopenharmony_ci#define ECMA_UINT128_CLZ_MAX4(name) \
248425bb815Sopenharmony_ci  ecma_uint4_clz[name.hi >> 60]
249425bb815Sopenharmony_ci
250425bb815Sopenharmony_ci#endif /* __GNUC__ || __clang__ */
251425bb815Sopenharmony_ci
252425bb815Sopenharmony_ci/**
253425bb815Sopenharmony_ci * @}
254425bb815Sopenharmony_ci */
255425bb815Sopenharmony_ci
256425bb815Sopenharmony_ci/**
257425bb815Sopenharmony_ci * Number.MAX_VALUE exponent part when using 64 bit float representation.
258425bb815Sopenharmony_ci */
259425bb815Sopenharmony_ci#define NUMBER_MAX_DECIMAL_EXPONENT 308
260425bb815Sopenharmony_ci/**
261425bb815Sopenharmony_ci * Number.MIN_VALUE exponent part when using 64 bit float representation.
262425bb815Sopenharmony_ci */
263425bb815Sopenharmony_ci#define NUMBER_MIN_DECIMAL_EXPONENT -324
264425bb815Sopenharmony_ci
265425bb815Sopenharmony_ci#elif !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
266425bb815Sopenharmony_ci
267425bb815Sopenharmony_ci/**
268425bb815Sopenharmony_ci * Number.MAX_VALUE exponent part when using 32 bit float representation.
269425bb815Sopenharmony_ci */
270425bb815Sopenharmony_ci#define NUMBER_MAX_DECIMAL_EXPONENT 38
271425bb815Sopenharmony_ci/**
272425bb815Sopenharmony_ci * Number.MIN_VALUE exponent part when using 32 bit float representation.
273425bb815Sopenharmony_ci */
274425bb815Sopenharmony_ci#define NUMBER_MIN_DECIMAL_EXPONENT -45
275425bb815Sopenharmony_ci
276425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
277425bb815Sopenharmony_ci
278425bb815Sopenharmony_ci/**
279425bb815Sopenharmony_ci * Value of epsilon
280425bb815Sopenharmony_ci */
281425bb815Sopenharmony_ci#define EPSILON 0.0000001
282425bb815Sopenharmony_ci
283425bb815Sopenharmony_ci/**
284425bb815Sopenharmony_ci * ECMA-defined conversion from string to number for different radixes (2, 8, 16).
285425bb815Sopenharmony_ci *
286425bb815Sopenharmony_ci * See also:
287425bb815Sopenharmony_ci *          ECMA-262 v5 9.3.1
288425bb815Sopenharmony_ci *          ECMA-262 v6 7.1.3.1
289425bb815Sopenharmony_ci *
290425bb815Sopenharmony_ci * @return NaN - if the conversion fails
291425bb815Sopenharmony_ci *         converted number - otherwise
292425bb815Sopenharmony_ci */
293425bb815Sopenharmony_cistatic ecma_number_t
294425bb815Sopenharmony_ciecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */
295425bb815Sopenharmony_ci                                     const lit_utf8_byte_t *end_p, /**< end of utf-8 string  */
296425bb815Sopenharmony_ci                                     uint32_t radix) /**< radix */
297425bb815Sopenharmony_ci{
298425bb815Sopenharmony_ci  JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16);
299425bb815Sopenharmony_ci  ecma_number_t num = ECMA_NUMBER_ZERO;
300425bb815Sopenharmony_ci
301425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
302425bb815Sopenharmony_ci  if (radix <= 8)
303425bb815Sopenharmony_ci  {
304425bb815Sopenharmony_ci    lit_code_point_t upper_limit = LIT_CHAR_0 + radix;
305425bb815Sopenharmony_ci
306425bb815Sopenharmony_ci    for (const lit_utf8_byte_t * iter_p = str_p;  iter_p <= end_p; iter_p++)
307425bb815Sopenharmony_ci    {
308425bb815Sopenharmony_ci      int32_t digit_value;
309425bb815Sopenharmony_ci
310425bb815Sopenharmony_ci      if (*iter_p >= LIT_CHAR_0 && *iter_p < upper_limit)
311425bb815Sopenharmony_ci      {
312425bb815Sopenharmony_ci        digit_value = (*iter_p - LIT_CHAR_0);
313425bb815Sopenharmony_ci      }
314425bb815Sopenharmony_ci      else
315425bb815Sopenharmony_ci      {
316425bb815Sopenharmony_ci        return ecma_number_make_nan ();
317425bb815Sopenharmony_ci      }
318425bb815Sopenharmony_ci
319425bb815Sopenharmony_ci      num = num * radix + (ecma_number_t) digit_value;
320425bb815Sopenharmony_ci    }
321425bb815Sopenharmony_ci
322425bb815Sopenharmony_ci    return num;
323425bb815Sopenharmony_ci  }
324425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
325425bb815Sopenharmony_ci
326425bb815Sopenharmony_ci  for (const lit_utf8_byte_t * iter_p = str_p; iter_p <= end_p; iter_p++)
327425bb815Sopenharmony_ci  {
328425bb815Sopenharmony_ci    int32_t digit_value;
329425bb815Sopenharmony_ci
330425bb815Sopenharmony_ci    if (*iter_p >= LIT_CHAR_0
331425bb815Sopenharmony_ci        && *iter_p <= LIT_CHAR_9)
332425bb815Sopenharmony_ci    {
333425bb815Sopenharmony_ci      digit_value = (*iter_p - LIT_CHAR_0);
334425bb815Sopenharmony_ci    }
335425bb815Sopenharmony_ci    else if (*iter_p >= LIT_CHAR_LOWERCASE_A
336425bb815Sopenharmony_ci            && *iter_p <= LIT_CHAR_LOWERCASE_F)
337425bb815Sopenharmony_ci    {
338425bb815Sopenharmony_ci      digit_value = 10 + (*iter_p - LIT_CHAR_LOWERCASE_A);
339425bb815Sopenharmony_ci    }
340425bb815Sopenharmony_ci    else if (*iter_p >= LIT_CHAR_UPPERCASE_A
341425bb815Sopenharmony_ci            && *iter_p <= LIT_CHAR_UPPERCASE_F)
342425bb815Sopenharmony_ci    {
343425bb815Sopenharmony_ci      digit_value = 10 + (*iter_p - LIT_CHAR_UPPERCASE_A);
344425bb815Sopenharmony_ci    }
345425bb815Sopenharmony_ci    else
346425bb815Sopenharmony_ci    {
347425bb815Sopenharmony_ci      return ecma_number_make_nan ();
348425bb815Sopenharmony_ci    }
349425bb815Sopenharmony_ci
350425bb815Sopenharmony_ci    num = num * radix + (ecma_number_t) digit_value;
351425bb815Sopenharmony_ci  }
352425bb815Sopenharmony_ci
353425bb815Sopenharmony_ci  return num;
354425bb815Sopenharmony_ci} /* ecma_utf8_string_to_number_by_radix */
355425bb815Sopenharmony_ci
356425bb815Sopenharmony_ci/**
357425bb815Sopenharmony_ci * ECMA-defined conversion of string to Number.
358425bb815Sopenharmony_ci *
359425bb815Sopenharmony_ci * See also:
360425bb815Sopenharmony_ci *          ECMA-262 v5, 9.3.1
361425bb815Sopenharmony_ci *
362425bb815Sopenharmony_ci * @return NaN - if the conversion fails
363425bb815Sopenharmony_ci *         converted number - otherwise
364425bb815Sopenharmony_ci */
365425bb815Sopenharmony_ciecma_number_t
366425bb815Sopenharmony_ciecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
367425bb815Sopenharmony_ci                            lit_utf8_size_t str_size) /**< string size */
368425bb815Sopenharmony_ci{
369425bb815Sopenharmony_ci  /* TODO: Check license issues */
370425bb815Sopenharmony_ci
371425bb815Sopenharmony_ci  if (str_size == 0)
372425bb815Sopenharmony_ci  {
373425bb815Sopenharmony_ci    return ECMA_NUMBER_ZERO;
374425bb815Sopenharmony_ci  }
375425bb815Sopenharmony_ci
376425bb815Sopenharmony_ci  ecma_string_trim_helper (&str_p, &str_size);
377425bb815Sopenharmony_ci  const lit_utf8_byte_t *end_p = str_p + (str_size - 1);
378425bb815Sopenharmony_ci
379425bb815Sopenharmony_ci  if (str_size < 1)
380425bb815Sopenharmony_ci  {
381425bb815Sopenharmony_ci    return ECMA_NUMBER_ZERO;
382425bb815Sopenharmony_ci  }
383425bb815Sopenharmony_ci
384425bb815Sopenharmony_ci  if (end_p >= str_p + 2
385425bb815Sopenharmony_ci      && str_p[0] == LIT_CHAR_0)
386425bb815Sopenharmony_ci  {
387425bb815Sopenharmony_ci    switch (LEXER_TO_ASCII_LOWERCASE (str_p[1]))
388425bb815Sopenharmony_ci    {
389425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_X :
390425bb815Sopenharmony_ci      {
391425bb815Sopenharmony_ci        return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 16);
392425bb815Sopenharmony_ci      }
393425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_O :
394425bb815Sopenharmony_ci      {
395425bb815Sopenharmony_ci        return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 8);
396425bb815Sopenharmony_ci      }
397425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_B :
398425bb815Sopenharmony_ci      {
399425bb815Sopenharmony_ci        return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 2);
400425bb815Sopenharmony_ci      }
401425bb815Sopenharmony_ci      default:
402425bb815Sopenharmony_ci      {
403425bb815Sopenharmony_ci        break;
404425bb815Sopenharmony_ci      }
405425bb815Sopenharmony_ci    }
406425bb815Sopenharmony_ci  }
407425bb815Sopenharmony_ci
408425bb815Sopenharmony_ci  bool sign = false; /* positive */
409425bb815Sopenharmony_ci
410425bb815Sopenharmony_ci  if (*str_p == LIT_CHAR_PLUS)
411425bb815Sopenharmony_ci  {
412425bb815Sopenharmony_ci    str_p++;
413425bb815Sopenharmony_ci  }
414425bb815Sopenharmony_ci  else if (*str_p == LIT_CHAR_MINUS)
415425bb815Sopenharmony_ci  {
416425bb815Sopenharmony_ci    sign = true; /* negative */
417425bb815Sopenharmony_ci
418425bb815Sopenharmony_ci    str_p++;
419425bb815Sopenharmony_ci  }
420425bb815Sopenharmony_ci
421425bb815Sopenharmony_ci  if (str_p > end_p)
422425bb815Sopenharmony_ci  {
423425bb815Sopenharmony_ci    return ecma_number_make_nan ();
424425bb815Sopenharmony_ci  }
425425bb815Sopenharmony_ci
426425bb815Sopenharmony_ci  /* Checking if significant part of parse string is equal to "Infinity" */
427425bb815Sopenharmony_ci  const lit_utf8_byte_t *infinity_zt_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL);
428425bb815Sopenharmony_ci
429425bb815Sopenharmony_ci  JERRY_ASSERT (strlen ((const char *) infinity_zt_str_p) == 8);
430425bb815Sopenharmony_ci
431425bb815Sopenharmony_ci  if ((end_p - str_p) == (8 - 1) && memcmp (infinity_zt_str_p, str_p, 8) == 0)
432425bb815Sopenharmony_ci  {
433425bb815Sopenharmony_ci    return ecma_number_make_infinity (sign);
434425bb815Sopenharmony_ci  }
435425bb815Sopenharmony_ci
436425bb815Sopenharmony_ci  uint64_t fraction_uint64 = 0;
437425bb815Sopenharmony_ci  uint32_t digits = 0;
438425bb815Sopenharmony_ci  int32_t e = 0;
439425bb815Sopenharmony_ci  bool digit_seen = false;
440425bb815Sopenharmony_ci
441425bb815Sopenharmony_ci  /* Parsing digits before dot (or before end of digits part if there is no dot in number) */
442425bb815Sopenharmony_ci  while (str_p <= end_p)
443425bb815Sopenharmony_ci  {
444425bb815Sopenharmony_ci    int32_t digit_value;
445425bb815Sopenharmony_ci
446425bb815Sopenharmony_ci    if (*str_p >= LIT_CHAR_0
447425bb815Sopenharmony_ci        && *str_p <= LIT_CHAR_9)
448425bb815Sopenharmony_ci    {
449425bb815Sopenharmony_ci      digit_seen = true;
450425bb815Sopenharmony_ci      digit_value = (*str_p - LIT_CHAR_0);
451425bb815Sopenharmony_ci    }
452425bb815Sopenharmony_ci    else
453425bb815Sopenharmony_ci    {
454425bb815Sopenharmony_ci      break;
455425bb815Sopenharmony_ci    }
456425bb815Sopenharmony_ci
457425bb815Sopenharmony_ci    if (digits != 0 || digit_value != 0)
458425bb815Sopenharmony_ci    {
459425bb815Sopenharmony_ci      if (digits < ECMA_NUMBER_MAX_DIGITS)
460425bb815Sopenharmony_ci      {
461425bb815Sopenharmony_ci        fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value;
462425bb815Sopenharmony_ci        digits++;
463425bb815Sopenharmony_ci      }
464425bb815Sopenharmony_ci      else
465425bb815Sopenharmony_ci      {
466425bb815Sopenharmony_ci        e++;
467425bb815Sopenharmony_ci      }
468425bb815Sopenharmony_ci    }
469425bb815Sopenharmony_ci
470425bb815Sopenharmony_ci    str_p++;
471425bb815Sopenharmony_ci  }
472425bb815Sopenharmony_ci
473425bb815Sopenharmony_ci  if (str_p <= end_p
474425bb815Sopenharmony_ci      && *str_p == LIT_CHAR_DOT)
475425bb815Sopenharmony_ci  {
476425bb815Sopenharmony_ci    str_p++;
477425bb815Sopenharmony_ci
478425bb815Sopenharmony_ci    if (!digit_seen && str_p > end_p)
479425bb815Sopenharmony_ci    {
480425bb815Sopenharmony_ci      return ecma_number_make_nan ();
481425bb815Sopenharmony_ci    }
482425bb815Sopenharmony_ci
483425bb815Sopenharmony_ci    /* Parsing number's part that is placed after dot */
484425bb815Sopenharmony_ci    while (str_p <= end_p)
485425bb815Sopenharmony_ci    {
486425bb815Sopenharmony_ci      int32_t digit_value;
487425bb815Sopenharmony_ci
488425bb815Sopenharmony_ci      if (*str_p >= LIT_CHAR_0
489425bb815Sopenharmony_ci          && *str_p <= LIT_CHAR_9)
490425bb815Sopenharmony_ci      {
491425bb815Sopenharmony_ci        digit_seen = true;
492425bb815Sopenharmony_ci        digit_value = (*str_p - LIT_CHAR_0);
493425bb815Sopenharmony_ci      }
494425bb815Sopenharmony_ci      else
495425bb815Sopenharmony_ci      {
496425bb815Sopenharmony_ci        break;
497425bb815Sopenharmony_ci      }
498425bb815Sopenharmony_ci
499425bb815Sopenharmony_ci      if (digits < ECMA_NUMBER_MAX_DIGITS)
500425bb815Sopenharmony_ci      {
501425bb815Sopenharmony_ci        if (digits != 0 || digit_value != 0)
502425bb815Sopenharmony_ci        {
503425bb815Sopenharmony_ci          fraction_uint64 = fraction_uint64 * 10 + (uint32_t) digit_value;
504425bb815Sopenharmony_ci          digits++;
505425bb815Sopenharmony_ci        }
506425bb815Sopenharmony_ci
507425bb815Sopenharmony_ci        e--;
508425bb815Sopenharmony_ci      }
509425bb815Sopenharmony_ci
510425bb815Sopenharmony_ci      str_p++;
511425bb815Sopenharmony_ci    }
512425bb815Sopenharmony_ci  }
513425bb815Sopenharmony_ci
514425bb815Sopenharmony_ci  /* Parsing exponent literal */
515425bb815Sopenharmony_ci  int32_t e_in_lit = 0;
516425bb815Sopenharmony_ci  bool e_in_lit_sign = false;
517425bb815Sopenharmony_ci
518425bb815Sopenharmony_ci  if (str_p <= end_p
519425bb815Sopenharmony_ci      && (*str_p == LIT_CHAR_LOWERCASE_E
520425bb815Sopenharmony_ci          || *str_p == LIT_CHAR_UPPERCASE_E))
521425bb815Sopenharmony_ci  {
522425bb815Sopenharmony_ci    str_p++;
523425bb815Sopenharmony_ci
524425bb815Sopenharmony_ci    if (!digit_seen || str_p > end_p)
525425bb815Sopenharmony_ci    {
526425bb815Sopenharmony_ci      return ecma_number_make_nan ();
527425bb815Sopenharmony_ci    }
528425bb815Sopenharmony_ci
529425bb815Sopenharmony_ci    if (*str_p == LIT_CHAR_PLUS)
530425bb815Sopenharmony_ci    {
531425bb815Sopenharmony_ci      str_p++;
532425bb815Sopenharmony_ci    }
533425bb815Sopenharmony_ci    else if (*str_p == LIT_CHAR_MINUS)
534425bb815Sopenharmony_ci    {
535425bb815Sopenharmony_ci      e_in_lit_sign = true;
536425bb815Sopenharmony_ci      str_p++;
537425bb815Sopenharmony_ci    }
538425bb815Sopenharmony_ci
539425bb815Sopenharmony_ci    if (str_p > end_p)
540425bb815Sopenharmony_ci    {
541425bb815Sopenharmony_ci      return ecma_number_make_nan ();
542425bb815Sopenharmony_ci    }
543425bb815Sopenharmony_ci
544425bb815Sopenharmony_ci    while (str_p <= end_p)
545425bb815Sopenharmony_ci    {
546425bb815Sopenharmony_ci      int32_t digit_value;
547425bb815Sopenharmony_ci
548425bb815Sopenharmony_ci      if (*str_p >= LIT_CHAR_0
549425bb815Sopenharmony_ci          && *str_p <= LIT_CHAR_9)
550425bb815Sopenharmony_ci      {
551425bb815Sopenharmony_ci        digit_value = (*str_p - LIT_CHAR_0);
552425bb815Sopenharmony_ci      }
553425bb815Sopenharmony_ci      else
554425bb815Sopenharmony_ci      {
555425bb815Sopenharmony_ci        return ecma_number_make_nan ();
556425bb815Sopenharmony_ci      }
557425bb815Sopenharmony_ci
558425bb815Sopenharmony_ci      e_in_lit = e_in_lit * 10 + digit_value;
559425bb815Sopenharmony_ci      int32_t e_check = e + (int32_t) digits - 1  + (e_in_lit_sign ? -e_in_lit : e_in_lit);
560425bb815Sopenharmony_ci
561425bb815Sopenharmony_ci      if (e_check > NUMBER_MAX_DECIMAL_EXPONENT)
562425bb815Sopenharmony_ci      {
563425bb815Sopenharmony_ci        return ecma_number_make_infinity (sign);
564425bb815Sopenharmony_ci      }
565425bb815Sopenharmony_ci      else if (e_check < NUMBER_MIN_DECIMAL_EXPONENT)
566425bb815Sopenharmony_ci      {
567425bb815Sopenharmony_ci        return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO;
568425bb815Sopenharmony_ci      }
569425bb815Sopenharmony_ci
570425bb815Sopenharmony_ci      str_p++;
571425bb815Sopenharmony_ci    }
572425bb815Sopenharmony_ci  }
573425bb815Sopenharmony_ci
574425bb815Sopenharmony_ci  /* Adding value of exponent literal to exponent value */
575425bb815Sopenharmony_ci  if (e_in_lit_sign)
576425bb815Sopenharmony_ci  {
577425bb815Sopenharmony_ci    e -= e_in_lit;
578425bb815Sopenharmony_ci  }
579425bb815Sopenharmony_ci  else
580425bb815Sopenharmony_ci  {
581425bb815Sopenharmony_ci    e += e_in_lit;
582425bb815Sopenharmony_ci  }
583425bb815Sopenharmony_ci
584425bb815Sopenharmony_ci  bool e_sign;
585425bb815Sopenharmony_ci
586425bb815Sopenharmony_ci  if (e < 0)
587425bb815Sopenharmony_ci  {
588425bb815Sopenharmony_ci    e_sign = true;
589425bb815Sopenharmony_ci    e = -e;
590425bb815Sopenharmony_ci  }
591425bb815Sopenharmony_ci  else
592425bb815Sopenharmony_ci  {
593425bb815Sopenharmony_ci    e_sign = false;
594425bb815Sopenharmony_ci  }
595425bb815Sopenharmony_ci
596425bb815Sopenharmony_ci  if (str_p <= end_p)
597425bb815Sopenharmony_ci  {
598425bb815Sopenharmony_ci    return ecma_number_make_nan ();
599425bb815Sopenharmony_ci  }
600425bb815Sopenharmony_ci
601425bb815Sopenharmony_ci  JERRY_ASSERT (str_p == end_p + 1);
602425bb815Sopenharmony_ci
603425bb815Sopenharmony_ci  if (fraction_uint64 == 0)
604425bb815Sopenharmony_ci  {
605425bb815Sopenharmony_ci    return sign ? -ECMA_NUMBER_ZERO : ECMA_NUMBER_ZERO;
606425bb815Sopenharmony_ci  }
607425bb815Sopenharmony_ci
608425bb815Sopenharmony_ci#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
609425bb815Sopenharmony_ci  /*
610425bb815Sopenharmony_ci   * 128-bit mantissa storage
611425bb815Sopenharmony_ci   *
612425bb815Sopenharmony_ci   * Normalized: |4 bits zero|124-bit mantissa with highest bit set to 1|
613425bb815Sopenharmony_ci   */
614425bb815Sopenharmony_ci  ecma_uint128_t fraction_uint128 = { 0, fraction_uint64 };
615425bb815Sopenharmony_ci
616425bb815Sopenharmony_ci  /* Normalizing mantissa */
617425bb815Sopenharmony_ci  int shift = 4 - ECMA_UINT128_CLZ_MAX63 (fraction_uint128);
618425bb815Sopenharmony_ci  if (shift < 0)
619425bb815Sopenharmony_ci  {
620425bb815Sopenharmony_ci    ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, -shift);
621425bb815Sopenharmony_ci  }
622425bb815Sopenharmony_ci  else
623425bb815Sopenharmony_ci  {
624425bb815Sopenharmony_ci    ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
625425bb815Sopenharmony_ci  }
626425bb815Sopenharmony_ci  int32_t binary_exponent = 1 + shift;
627425bb815Sopenharmony_ci
628425bb815Sopenharmony_ci  if (!e_sign)
629425bb815Sopenharmony_ci  {
630425bb815Sopenharmony_ci    /* positive or zero decimal exponent */
631425bb815Sopenharmony_ci    JERRY_ASSERT (e >= 0);
632425bb815Sopenharmony_ci
633425bb815Sopenharmony_ci    while (e > 0)
634425bb815Sopenharmony_ci    {
635425bb815Sopenharmony_ci      JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
636425bb815Sopenharmony_ci
637425bb815Sopenharmony_ci      ECMA_UINT128_MUL10 (fraction_uint128);
638425bb815Sopenharmony_ci
639425bb815Sopenharmony_ci      e--;
640425bb815Sopenharmony_ci
641425bb815Sopenharmony_ci      /* Normalizing mantissa */
642425bb815Sopenharmony_ci      shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
643425bb815Sopenharmony_ci      JERRY_ASSERT (shift >= 0);
644425bb815Sopenharmony_ci      ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
645425bb815Sopenharmony_ci      binary_exponent += shift;
646425bb815Sopenharmony_ci    }
647425bb815Sopenharmony_ci  }
648425bb815Sopenharmony_ci  else
649425bb815Sopenharmony_ci  {
650425bb815Sopenharmony_ci    /* negative decimal exponent */
651425bb815Sopenharmony_ci    JERRY_ASSERT (e != 0);
652425bb815Sopenharmony_ci
653425bb815Sopenharmony_ci    while (e > 0)
654425bb815Sopenharmony_ci    {
655425bb815Sopenharmony_ci      /* Denormalizing mantissa, moving highest 1 to bit 127 */
656425bb815Sopenharmony_ci      shift = ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
657425bb815Sopenharmony_ci      JERRY_ASSERT (shift <= 4);
658425bb815Sopenharmony_ci      ECMA_UINT128_LEFT_SHIFT_MAX63 (fraction_uint128, shift);
659425bb815Sopenharmony_ci      binary_exponent -= shift;
660425bb815Sopenharmony_ci
661425bb815Sopenharmony_ci      JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128));
662425bb815Sopenharmony_ci
663425bb815Sopenharmony_ci      ECMA_UINT128_DIV10 (fraction_uint128);
664425bb815Sopenharmony_ci
665425bb815Sopenharmony_ci      e--;
666425bb815Sopenharmony_ci    }
667425bb815Sopenharmony_ci
668425bb815Sopenharmony_ci    /* Normalizing mantissa */
669425bb815Sopenharmony_ci    shift = 4 - ECMA_UINT128_CLZ_MAX4 (fraction_uint128);
670425bb815Sopenharmony_ci    JERRY_ASSERT (shift >= 0);
671425bb815Sopenharmony_ci    ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, shift);
672425bb815Sopenharmony_ci    binary_exponent += shift;
673425bb815Sopenharmony_ci
674425bb815Sopenharmony_ci    JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
675425bb815Sopenharmony_ci  }
676425bb815Sopenharmony_ci
677425bb815Sopenharmony_ci  JERRY_ASSERT (!ECMA_UINT128_IS_ZERO (fraction_uint128));
678425bb815Sopenharmony_ci  JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 4);
679425bb815Sopenharmony_ci
680425bb815Sopenharmony_ci  /*
681425bb815Sopenharmony_ci   * Preparing mantissa for conversion to 52-bit representation, converting it to:
682425bb815Sopenharmony_ci   *
683425bb815Sopenharmony_ci   * |11 zero bits|1|116 mantissa bits|
684425bb815Sopenharmony_ci   */
685425bb815Sopenharmony_ci  ECMA_UINT128_RIGHT_SHIFT_MAX63 (fraction_uint128, 7u);
686425bb815Sopenharmony_ci  binary_exponent += 7;
687425bb815Sopenharmony_ci
688425bb815Sopenharmony_ci  JERRY_ASSERT (ECMA_UINT128_CLZ_MAX63 (fraction_uint128) == 11);
689425bb815Sopenharmony_ci
690425bb815Sopenharmony_ci  fraction_uint64 = ecma_round_high_to_uint64 (&fraction_uint128);
691425bb815Sopenharmony_ci
692425bb815Sopenharmony_ci  return ecma_number_make_from_sign_mantissa_and_exponent (sign, fraction_uint64, binary_exponent);
693425bb815Sopenharmony_ci#elif !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
694425bb815Sopenharmony_ci  /* Less precise conversion */
695425bb815Sopenharmony_ci  ecma_number_t num = (ecma_number_t) (uint32_t) fraction_uint64;
696425bb815Sopenharmony_ci
697425bb815Sopenharmony_ci  ecma_number_t m = e_sign ? (ecma_number_t) 0.1 : (ecma_number_t) 10.0;
698425bb815Sopenharmony_ci
699425bb815Sopenharmony_ci  while (e)
700425bb815Sopenharmony_ci  {
701425bb815Sopenharmony_ci    if (e % 2)
702425bb815Sopenharmony_ci    {
703425bb815Sopenharmony_ci      num *= m;
704425bb815Sopenharmony_ci    }
705425bb815Sopenharmony_ci
706425bb815Sopenharmony_ci    m *= m;
707425bb815Sopenharmony_ci    e /= 2;
708425bb815Sopenharmony_ci  }
709425bb815Sopenharmony_ci
710425bb815Sopenharmony_ci  return num;
711425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
712425bb815Sopenharmony_ci} /* ecma_utf8_string_to_number */
713425bb815Sopenharmony_ci
714425bb815Sopenharmony_ci/**
715425bb815Sopenharmony_ci * ECMA-defined conversion of UInt32 to String (zero-terminated).
716425bb815Sopenharmony_ci *
717425bb815Sopenharmony_ci * See also:
718425bb815Sopenharmony_ci *          ECMA-262 v5, 9.8.1
719425bb815Sopenharmony_ci *
720425bb815Sopenharmony_ci * @return number of bytes copied to buffer
721425bb815Sopenharmony_ci */
722425bb815Sopenharmony_cilit_utf8_size_t
723425bb815Sopenharmony_ciecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */
724425bb815Sopenharmony_ci                            lit_utf8_byte_t *out_buffer_p, /**< buffer for string */
725425bb815Sopenharmony_ci                            lit_utf8_size_t buffer_size) /**< size of buffer */
726425bb815Sopenharmony_ci{
727425bb815Sopenharmony_ci  lit_utf8_byte_t *buf_p = out_buffer_p + buffer_size;
728425bb815Sopenharmony_ci
729425bb815Sopenharmony_ci  do
730425bb815Sopenharmony_ci  {
731425bb815Sopenharmony_ci    JERRY_ASSERT (buf_p >= out_buffer_p);
732425bb815Sopenharmony_ci
733425bb815Sopenharmony_ci    buf_p--;
734425bb815Sopenharmony_ci    *buf_p = (lit_utf8_byte_t) ((value % 10) + LIT_CHAR_0);
735425bb815Sopenharmony_ci    value /= 10;
736425bb815Sopenharmony_ci  }
737425bb815Sopenharmony_ci  while (value != 0);
738425bb815Sopenharmony_ci
739425bb815Sopenharmony_ci  JERRY_ASSERT (buf_p >= out_buffer_p);
740425bb815Sopenharmony_ci
741425bb815Sopenharmony_ci  lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (out_buffer_p + buffer_size - buf_p);
742425bb815Sopenharmony_ci
743425bb815Sopenharmony_ci  if (JERRY_LIKELY (buf_p != out_buffer_p))
744425bb815Sopenharmony_ci  {
745425bb815Sopenharmony_ci    memmove (out_buffer_p, buf_p, bytes_copied);
746425bb815Sopenharmony_ci  }
747425bb815Sopenharmony_ci
748425bb815Sopenharmony_ci  return bytes_copied;
749425bb815Sopenharmony_ci} /* ecma_uint32_to_utf8_string */
750425bb815Sopenharmony_ci
751425bb815Sopenharmony_ci/**
752425bb815Sopenharmony_ci * ECMA-defined conversion of Number value to UInt32 value
753425bb815Sopenharmony_ci *
754425bb815Sopenharmony_ci * See also:
755425bb815Sopenharmony_ci *          ECMA-262 v5, 9.6
756425bb815Sopenharmony_ci *
757425bb815Sopenharmony_ci * @return 32-bit unsigned integer - result of conversion.
758425bb815Sopenharmony_ci */
759425bb815Sopenharmony_ciuint32_t
760425bb815Sopenharmony_ciecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */
761425bb815Sopenharmony_ci{
762425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (ecma_number_is_zero (num) || !ecma_number_is_finite (num)))
763425bb815Sopenharmony_ci  {
764425bb815Sopenharmony_ci    return 0;
765425bb815Sopenharmony_ci  }
766425bb815Sopenharmony_ci
767425bb815Sopenharmony_ci  const bool sign = ecma_number_is_negative (num);
768425bb815Sopenharmony_ci  const ecma_number_t abs_num = sign ? -num : num;
769425bb815Sopenharmony_ci
770425bb815Sopenharmony_ci  /* 2 ^ 32 */
771425bb815Sopenharmony_ci  const uint64_t uint64_2_pow_32 = (1ull << 32);
772425bb815Sopenharmony_ci
773425bb815Sopenharmony_ci  const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32;
774425bb815Sopenharmony_ci
775425bb815Sopenharmony_ci  ecma_number_t num_in_uint32_range;
776425bb815Sopenharmony_ci
777425bb815Sopenharmony_ci  if (abs_num >= num_2_pow_32)
778425bb815Sopenharmony_ci  {
779425bb815Sopenharmony_ci    num_in_uint32_range = ecma_number_calc_remainder (abs_num,
780425bb815Sopenharmony_ci                                                      num_2_pow_32);
781425bb815Sopenharmony_ci  }
782425bb815Sopenharmony_ci  else
783425bb815Sopenharmony_ci  {
784425bb815Sopenharmony_ci    num_in_uint32_range = abs_num;
785425bb815Sopenharmony_ci  }
786425bb815Sopenharmony_ci
787425bb815Sopenharmony_ci  /* Check that the floating point value can be represented with uint32_t. */
788425bb815Sopenharmony_ci  JERRY_ASSERT (num_in_uint32_range < uint64_2_pow_32);
789425bb815Sopenharmony_ci  uint32_t uint32_num = (uint32_t) num_in_uint32_range;
790425bb815Sopenharmony_ci
791425bb815Sopenharmony_ci  const uint32_t ret = sign ? -uint32_num : uint32_num;
792425bb815Sopenharmony_ci
793425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
794425bb815Sopenharmony_ci  if (sign
795425bb815Sopenharmony_ci      && uint32_num != 0)
796425bb815Sopenharmony_ci  {
797425bb815Sopenharmony_ci    JERRY_ASSERT (ret == uint64_2_pow_32 - uint32_num);
798425bb815Sopenharmony_ci  }
799425bb815Sopenharmony_ci  else
800425bb815Sopenharmony_ci  {
801425bb815Sopenharmony_ci    JERRY_ASSERT (ret == uint32_num);
802425bb815Sopenharmony_ci  }
803425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
804425bb815Sopenharmony_ci
805425bb815Sopenharmony_ci  return ret;
806425bb815Sopenharmony_ci} /* ecma_number_to_uint32 */
807425bb815Sopenharmony_ci
808425bb815Sopenharmony_ci/**
809425bb815Sopenharmony_ci * ECMA-defined conversion of Number value to Int32 value
810425bb815Sopenharmony_ci *
811425bb815Sopenharmony_ci * See also:
812425bb815Sopenharmony_ci *          ECMA-262 v5, 9.5
813425bb815Sopenharmony_ci *
814425bb815Sopenharmony_ci * @return 32-bit signed integer - result of conversion.
815425bb815Sopenharmony_ci */
816425bb815Sopenharmony_ciint32_t
817425bb815Sopenharmony_ciecma_number_to_int32 (ecma_number_t num) /**< ecma-number */
818425bb815Sopenharmony_ci{
819425bb815Sopenharmony_ci  uint32_t uint32_num = ecma_number_to_uint32 (num);
820425bb815Sopenharmony_ci
821425bb815Sopenharmony_ci  /* 2 ^ 32 */
822425bb815Sopenharmony_ci  const int64_t int64_2_pow_32 = (1ll << 32);
823425bb815Sopenharmony_ci
824425bb815Sopenharmony_ci  /* 2 ^ 31 */
825425bb815Sopenharmony_ci  const uint32_t uint32_2_pow_31 = (1ull << 31);
826425bb815Sopenharmony_ci
827425bb815Sopenharmony_ci  int32_t ret;
828425bb815Sopenharmony_ci
829425bb815Sopenharmony_ci  if (uint32_num >= uint32_2_pow_31)
830425bb815Sopenharmony_ci  {
831425bb815Sopenharmony_ci    ret = (int32_t) (uint32_num - int64_2_pow_32);
832425bb815Sopenharmony_ci  }
833425bb815Sopenharmony_ci  else
834425bb815Sopenharmony_ci  {
835425bb815Sopenharmony_ci    ret = (int32_t) uint32_num;
836425bb815Sopenharmony_ci  }
837425bb815Sopenharmony_ci
838425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
839425bb815Sopenharmony_ci  int64_t int64_num = uint32_num;
840425bb815Sopenharmony_ci
841425bb815Sopenharmony_ci  JERRY_ASSERT (int64_num >= 0);
842425bb815Sopenharmony_ci
843425bb815Sopenharmony_ci  if (int64_num >= uint32_2_pow_31)
844425bb815Sopenharmony_ci  {
845425bb815Sopenharmony_ci    JERRY_ASSERT (ret == int64_num - int64_2_pow_32);
846425bb815Sopenharmony_ci  }
847425bb815Sopenharmony_ci  else
848425bb815Sopenharmony_ci  {
849425bb815Sopenharmony_ci    JERRY_ASSERT (ret == int64_num);
850425bb815Sopenharmony_ci  }
851425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
852425bb815Sopenharmony_ci
853425bb815Sopenharmony_ci  return ret;
854425bb815Sopenharmony_ci} /* ecma_number_to_int32 */
855425bb815Sopenharmony_ci
856425bb815Sopenharmony_ci/**
857425bb815Sopenharmony_ci  * Perform conversion of ecma-number to decimal representation with decimal exponent.
858425bb815Sopenharmony_ci  *
859425bb815Sopenharmony_ci  * Note:
860425bb815Sopenharmony_ci  *      The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5:
861425bb815Sopenharmony_ci  *         - parameter out_digits_p corresponds to s, the digits of the number;
862425bb815Sopenharmony_ci  *         - parameter out_decimal_exp_p corresponds to n, the decimal exponent;
863425bb815Sopenharmony_ci  *         - return value corresponds to k, the number of digits.
864425bb815Sopenharmony_ci  *
865425bb815Sopenharmony_ci  * @return the number of digits
866425bb815Sopenharmony_ci  */
867425bb815Sopenharmony_cilit_utf8_size_t
868425bb815Sopenharmony_ciecma_number_to_decimal (ecma_number_t num, /**< ecma-number */
869425bb815Sopenharmony_ci                        lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */
870425bb815Sopenharmony_ci                        int32_t *out_decimal_exp_p) /**< [out] decimal exponent */
871425bb815Sopenharmony_ci{
872425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (num));
873425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_zero (num));
874425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_infinity (num));
875425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_negative (num));
876425bb815Sopenharmony_ci
877425bb815Sopenharmony_ci  return ecma_errol0_dtoa ((double) num, out_digits_p, out_decimal_exp_p);
878425bb815Sopenharmony_ci} /* ecma_number_to_decimal */
879425bb815Sopenharmony_ci
880425bb815Sopenharmony_ci/**
881425bb815Sopenharmony_ci * Calculate the number of digits from the given double value whithout franction part
882425bb815Sopenharmony_ci *
883425bb815Sopenharmony_ci * @return number of digits
884425bb815Sopenharmony_ci */
885425bb815Sopenharmony_ciinline static int32_t JERRY_ATTR_ALWAYS_INLINE
886425bb815Sopenharmony_ciecma_number_of_digits (double val) /**< ecma number */
887425bb815Sopenharmony_ci{
888425bb815Sopenharmony_ci  JERRY_ASSERT (fabs (fmod (val, 1.0)) < EPSILON);
889425bb815Sopenharmony_ci  int32_t exponent = 0;
890425bb815Sopenharmony_ci
891425bb815Sopenharmony_ci  while (val >= 1.0)
892425bb815Sopenharmony_ci  {
893425bb815Sopenharmony_ci    val /= 10.0;
894425bb815Sopenharmony_ci    exponent++;
895425bb815Sopenharmony_ci  }
896425bb815Sopenharmony_ci
897425bb815Sopenharmony_ci  return exponent;
898425bb815Sopenharmony_ci} /* ecma_number_of_digits */
899425bb815Sopenharmony_ci
900425bb815Sopenharmony_ci/**
901425bb815Sopenharmony_ci * Convert double value to ASCII
902425bb815Sopenharmony_ci */
903425bb815Sopenharmony_ciinline static void JERRY_ATTR_ALWAYS_INLINE
904425bb815Sopenharmony_ciecma_double_to_ascii (double val, /**< ecma number */
905425bb815Sopenharmony_ci                      lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */
906425bb815Sopenharmony_ci                      int32_t num_of_digits, /**< number of digits */
907425bb815Sopenharmony_ci                      int32_t *exp_p) /**< [out] exponent */
908425bb815Sopenharmony_ci{
909425bb815Sopenharmony_ci  int32_t char_cnt = 0;
910425bb815Sopenharmony_ci
911425bb815Sopenharmony_ci  double divider = 10.0;
912425bb815Sopenharmony_ci  double prev_residual;
913425bb815Sopenharmony_ci  double mod_res = fmod (val, divider);
914425bb815Sopenharmony_ci
915425bb815Sopenharmony_ci  buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) mod_res + '0');
916425bb815Sopenharmony_ci  divider *= 10.0;
917425bb815Sopenharmony_ci  prev_residual = mod_res;
918425bb815Sopenharmony_ci
919425bb815Sopenharmony_ci  while (char_cnt < num_of_digits)
920425bb815Sopenharmony_ci  {
921425bb815Sopenharmony_ci    mod_res = fmod (val, divider);
922425bb815Sopenharmony_ci    double residual = mod_res - prev_residual;
923425bb815Sopenharmony_ci    buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) (residual / (divider / 10.0)) + '0');
924425bb815Sopenharmony_ci
925425bb815Sopenharmony_ci    divider *= 10.0;
926425bb815Sopenharmony_ci    prev_residual = mod_res;
927425bb815Sopenharmony_ci  }
928425bb815Sopenharmony_ci
929425bb815Sopenharmony_ci  *exp_p = char_cnt;
930425bb815Sopenharmony_ci} /* ecma_double_to_ascii */
931425bb815Sopenharmony_ci
932425bb815Sopenharmony_ci/**
933425bb815Sopenharmony_ci * Double to binary floating-point number conversion
934425bb815Sopenharmony_ci *
935425bb815Sopenharmony_ci * @return number of generated digits
936425bb815Sopenharmony_ci */
937425bb815Sopenharmony_cistatic inline lit_utf8_size_t JERRY_ATTR_ALWAYS_INLINE
938425bb815Sopenharmony_ciecma_double_to_binary_floating_point (double val, /**< ecma number */
939425bb815Sopenharmony_ci                                      lit_utf8_byte_t *buffer_p, /**< buffer to generate digits into */
940425bb815Sopenharmony_ci                                      int32_t *exp_p) /**< [out] exponent */
941425bb815Sopenharmony_ci{
942425bb815Sopenharmony_ci  int32_t char_cnt = 0;
943425bb815Sopenharmony_ci  double integer_part, fraction_part;
944425bb815Sopenharmony_ci
945425bb815Sopenharmony_ci  fraction_part = fmod (val, 1.0);
946425bb815Sopenharmony_ci  integer_part = floor (val);
947425bb815Sopenharmony_ci  int32_t num_of_digits = ecma_number_of_digits (integer_part);
948425bb815Sopenharmony_ci
949425bb815Sopenharmony_ci  if (fabs (integer_part) < EPSILON)
950425bb815Sopenharmony_ci  {
951425bb815Sopenharmony_ci    buffer_p[0] = '0';
952425bb815Sopenharmony_ci    char_cnt++;
953425bb815Sopenharmony_ci  }
954425bb815Sopenharmony_ci  else if (num_of_digits <= 16) /* Ensure that integer_part is not rounded */
955425bb815Sopenharmony_ci  {
956425bb815Sopenharmony_ci    while (integer_part > 0.0)
957425bb815Sopenharmony_ci    {
958425bb815Sopenharmony_ci      buffer_p[num_of_digits - 1 - char_cnt++] = (lit_utf8_byte_t) ((int) fmod (integer_part, 10.0) + '0');
959425bb815Sopenharmony_ci      integer_part = floor (integer_part / 10.0);
960425bb815Sopenharmony_ci    }
961425bb815Sopenharmony_ci  }
962425bb815Sopenharmony_ci  else if (num_of_digits <= 21)
963425bb815Sopenharmony_ci  {
964425bb815Sopenharmony_ci    ecma_double_to_ascii (integer_part, buffer_p, num_of_digits, &char_cnt);
965425bb815Sopenharmony_ci  }
966425bb815Sopenharmony_ci  else
967425bb815Sopenharmony_ci  {
968425bb815Sopenharmony_ci    /* According to ECMA-262 v5, 15.7.4.5, step 7: if x >= 10^21, then execution will continue with
969425bb815Sopenharmony_ci     * ToString(x) so in this case no further conversions are required. Number 21 in the else if condition
970425bb815Sopenharmony_ci     * above must be kept in sync with the number 21 in ecma_builtin_number_prototype_object_to_fixed
971425bb815Sopenharmony_ci     * method, step 7. */
972425bb815Sopenharmony_ci    *exp_p = num_of_digits;
973425bb815Sopenharmony_ci    return 0;
974425bb815Sopenharmony_ci  }
975425bb815Sopenharmony_ci
976425bb815Sopenharmony_ci  *exp_p = char_cnt;
977425bb815Sopenharmony_ci
978425bb815Sopenharmony_ci  while (fraction_part > 0 && char_cnt < ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER - 1)
979425bb815Sopenharmony_ci  {
980425bb815Sopenharmony_ci    fraction_part *= 10;
981425bb815Sopenharmony_ci    double tmp = fraction_part;
982425bb815Sopenharmony_ci    fraction_part = fmod (fraction_part, 1.0);
983425bb815Sopenharmony_ci    integer_part = floor (tmp);
984425bb815Sopenharmony_ci    buffer_p[char_cnt++] = (lit_utf8_byte_t) ('0' + (int) integer_part);
985425bb815Sopenharmony_ci  }
986425bb815Sopenharmony_ci
987425bb815Sopenharmony_ci  buffer_p[char_cnt] = '\0';
988425bb815Sopenharmony_ci
989425bb815Sopenharmony_ci  return (lit_utf8_size_t) (char_cnt - *exp_p);
990425bb815Sopenharmony_ci} /* ecma_double_to_binary_floating_point */
991425bb815Sopenharmony_ci
992425bb815Sopenharmony_ci/**
993425bb815Sopenharmony_ci * Perform conversion of ecma-number to equivalent binary floating-point number representation with decimal exponent.
994425bb815Sopenharmony_ci *
995425bb815Sopenharmony_ci * Note:
996425bb815Sopenharmony_ci *      The calculated values correspond to s, n, k parameters in ECMA-262 v5, 9.8.1, item 5:
997425bb815Sopenharmony_ci *         - parameter out_digits_p corresponds to s, the digits of the number;
998425bb815Sopenharmony_ci *         - parameter out_decimal_exp_p corresponds to n, the decimal exponent;
999425bb815Sopenharmony_ci *         - return value corresponds to k, the number of digits.
1000425bb815Sopenharmony_ci *
1001425bb815Sopenharmony_ci * @return the number of digits
1002425bb815Sopenharmony_ci */
1003425bb815Sopenharmony_cilit_utf8_size_t
1004425bb815Sopenharmony_ciecma_number_to_binary_floating_point_number (ecma_number_t num, /**< ecma-number */
1005425bb815Sopenharmony_ci                                             lit_utf8_byte_t *out_digits_p, /**< [out] buffer to fill with digits */
1006425bb815Sopenharmony_ci                                             int32_t *out_decimal_exp_p) /**< [out] decimal exponent */
1007425bb815Sopenharmony_ci{
1008425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (num));
1009425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_zero (num));
1010425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_infinity (num));
1011425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_negative (num));
1012425bb815Sopenharmony_ci
1013425bb815Sopenharmony_ci  return ecma_double_to_binary_floating_point ((double) num, out_digits_p, out_decimal_exp_p);
1014425bb815Sopenharmony_ci} /* ecma_number_to_binary_floating_point_number */
1015425bb815Sopenharmony_ci
1016425bb815Sopenharmony_ci/**
1017425bb815Sopenharmony_ci * Convert ecma-number to zero-terminated string
1018425bb815Sopenharmony_ci *
1019425bb815Sopenharmony_ci * See also:
1020425bb815Sopenharmony_ci *          ECMA-262 v5, 9.8.1
1021425bb815Sopenharmony_ci *
1022425bb815Sopenharmony_ci *
1023425bb815Sopenharmony_ci * @return size of utf-8 string
1024425bb815Sopenharmony_ci */
1025425bb815Sopenharmony_cilit_utf8_size_t
1026425bb815Sopenharmony_ciecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */
1027425bb815Sopenharmony_ci                            lit_utf8_byte_t *buffer_p, /**< buffer for utf-8 string */
1028425bb815Sopenharmony_ci                            lit_utf8_size_t buffer_size) /**< size of buffer */
1029425bb815Sopenharmony_ci{
1030425bb815Sopenharmony_ci  lit_utf8_byte_t *dst_p;
1031425bb815Sopenharmony_ci
1032425bb815Sopenharmony_ci  if (ecma_number_is_nan (num))
1033425bb815Sopenharmony_ci  {
1034425bb815Sopenharmony_ci    /* 1. */
1035425bb815Sopenharmony_ci    dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_NAN, buffer_p, buffer_size);
1036425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1037425bb815Sopenharmony_ci  }
1038425bb815Sopenharmony_ci
1039425bb815Sopenharmony_ci  if (ecma_number_is_zero (num))
1040425bb815Sopenharmony_ci  {
1041425bb815Sopenharmony_ci    /* 2. */
1042425bb815Sopenharmony_ci    *buffer_p = LIT_CHAR_0;
1043425bb815Sopenharmony_ci    JERRY_ASSERT (1 <= buffer_size);
1044425bb815Sopenharmony_ci    return 1;
1045425bb815Sopenharmony_ci  }
1046425bb815Sopenharmony_ci
1047425bb815Sopenharmony_ci  dst_p = buffer_p;
1048425bb815Sopenharmony_ci
1049425bb815Sopenharmony_ci  if (ecma_number_is_negative (num))
1050425bb815Sopenharmony_ci  {
1051425bb815Sopenharmony_ci    /* 3. */
1052425bb815Sopenharmony_ci    *dst_p++ = LIT_CHAR_MINUS;
1053425bb815Sopenharmony_ci    num = -num;
1054425bb815Sopenharmony_ci  }
1055425bb815Sopenharmony_ci
1056425bb815Sopenharmony_ci  if (ecma_number_is_infinity (num))
1057425bb815Sopenharmony_ci  {
1058425bb815Sopenharmony_ci    /* 4. */
1059425bb815Sopenharmony_ci    dst_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_INFINITY_UL, dst_p,
1060425bb815Sopenharmony_ci                                             (lit_utf8_size_t) (buffer_p + buffer_size - dst_p));
1061425bb815Sopenharmony_ci    JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1062425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1063425bb815Sopenharmony_ci  }
1064425bb815Sopenharmony_ci
1065425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_number_get_next (ecma_number_get_prev (num)) == num);
1066425bb815Sopenharmony_ci
1067425bb815Sopenharmony_ci  /* 5. */
1068425bb815Sopenharmony_ci  uint32_t num_uint32 = ecma_number_to_uint32 (num);
1069425bb815Sopenharmony_ci
1070425bb815Sopenharmony_ci  if (((ecma_number_t) num_uint32) == num)
1071425bb815Sopenharmony_ci  {
1072425bb815Sopenharmony_ci    dst_p += ecma_uint32_to_utf8_string (num_uint32, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p));
1073425bb815Sopenharmony_ci    JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1074425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1075425bb815Sopenharmony_ci  }
1076425bb815Sopenharmony_ci
1077425bb815Sopenharmony_ci  /* decimal exponent */
1078425bb815Sopenharmony_ci  int32_t n;
1079425bb815Sopenharmony_ci  /* number of digits in mantissa */
1080425bb815Sopenharmony_ci  int32_t k;
1081425bb815Sopenharmony_ci
1082425bb815Sopenharmony_ci  k = (int32_t) ecma_number_to_decimal (num, dst_p, &n);
1083425bb815Sopenharmony_ci
1084425bb815Sopenharmony_ci  if (k <= n && n <= 21)
1085425bb815Sopenharmony_ci  {
1086425bb815Sopenharmony_ci    /* 6. */
1087425bb815Sopenharmony_ci    dst_p += k;
1088425bb815Sopenharmony_ci
1089425bb815Sopenharmony_ci    memset (dst_p, LIT_CHAR_0, (size_t) (n - k));
1090425bb815Sopenharmony_ci    dst_p += n - k;
1091425bb815Sopenharmony_ci
1092425bb815Sopenharmony_ci    JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1093425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1094425bb815Sopenharmony_ci  }
1095425bb815Sopenharmony_ci
1096425bb815Sopenharmony_ci  if (0 < n && n <= 21)
1097425bb815Sopenharmony_ci  {
1098425bb815Sopenharmony_ci    /* 7. */
1099425bb815Sopenharmony_ci    memmove (dst_p + n + 1, dst_p + n, (size_t) (k - n));
1100425bb815Sopenharmony_ci    *(dst_p + n) = LIT_CHAR_DOT;
1101425bb815Sopenharmony_ci    dst_p += k + 1;
1102425bb815Sopenharmony_ci
1103425bb815Sopenharmony_ci    JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1104425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1105425bb815Sopenharmony_ci  }
1106425bb815Sopenharmony_ci
1107425bb815Sopenharmony_ci  if (-6 < n && n <= 0)
1108425bb815Sopenharmony_ci  {
1109425bb815Sopenharmony_ci    /* 8. */
1110425bb815Sopenharmony_ci    memmove (dst_p + 2 - n, dst_p, (size_t) k);
1111425bb815Sopenharmony_ci    memset (dst_p + 2, LIT_CHAR_0, (size_t) -n);
1112425bb815Sopenharmony_ci    *dst_p = LIT_CHAR_0;
1113425bb815Sopenharmony_ci    *(dst_p + 1) = LIT_CHAR_DOT;
1114425bb815Sopenharmony_ci    dst_p += k - n + 2;
1115425bb815Sopenharmony_ci
1116425bb815Sopenharmony_ci    JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1117425bb815Sopenharmony_ci    return (lit_utf8_size_t) (dst_p - buffer_p);
1118425bb815Sopenharmony_ci  }
1119425bb815Sopenharmony_ci
1120425bb815Sopenharmony_ci  if (k == 1)
1121425bb815Sopenharmony_ci  {
1122425bb815Sopenharmony_ci    /* 9. */
1123425bb815Sopenharmony_ci    dst_p++;
1124425bb815Sopenharmony_ci  }
1125425bb815Sopenharmony_ci  else
1126425bb815Sopenharmony_ci  {
1127425bb815Sopenharmony_ci    /* 10. */
1128425bb815Sopenharmony_ci    memmove (dst_p + 2, dst_p + 1, (size_t) (k - 1));
1129425bb815Sopenharmony_ci    *(dst_p + 1) = LIT_CHAR_DOT;
1130425bb815Sopenharmony_ci    dst_p += k + 1;
1131425bb815Sopenharmony_ci  }
1132425bb815Sopenharmony_ci
1133425bb815Sopenharmony_ci  /* 9., 10. */
1134425bb815Sopenharmony_ci  *dst_p++ = LIT_CHAR_LOWERCASE_E;
1135425bb815Sopenharmony_ci  *dst_p++ = (n >= 1) ? LIT_CHAR_PLUS : LIT_CHAR_MINUS;
1136425bb815Sopenharmony_ci  uint32_t t = (uint32_t) (n >= 1 ? (n - 1) : -(n - 1));
1137425bb815Sopenharmony_ci
1138425bb815Sopenharmony_ci  dst_p += ecma_uint32_to_utf8_string (t, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p));
1139425bb815Sopenharmony_ci
1140425bb815Sopenharmony_ci  JERRY_ASSERT (dst_p <= buffer_p + buffer_size);
1141425bb815Sopenharmony_ci
1142425bb815Sopenharmony_ci  return (lit_utf8_size_t) (dst_p - buffer_p);
1143425bb815Sopenharmony_ci} /* ecma_number_to_utf8_string */
1144425bb815Sopenharmony_ci
1145425bb815Sopenharmony_ci/**
1146425bb815Sopenharmony_ci * @}
1147425bb815Sopenharmony_ci * @}
1148425bb815Sopenharmony_ci */
1149