Coverage Report

Created: 2025-11-11 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsNumber.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2025  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#include "xsAll.h"
39
40
static txSlot* fxCheckNumber(txMachine* the, txSlot* it);
41
42
void fxBuildNumber(txMachine* the)
43
31.0k
{
44
31.0k
  txSlot* slot;
45
  
46
31.0k
  mxPushNumber((txNumber)C_INFINITY);
47
31.0k
  mxPull(mxInfinity);
48
31.0k
  mxPushNumber((txNumber)C_NAN);
49
31.0k
  mxPull(mxNaN);
50
51
31.0k
  mxPush(mxObjectPrototype);
52
31.0k
  slot = fxLastProperty(the, fxNewNumberInstance(the));
53
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toExponential), 1, mxID(_toExponential), XS_DONT_ENUM_FLAG);
54
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toFixed), 1, mxID(_toFixed), XS_DONT_ENUM_FLAG);
55
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
56
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toPrecision), 1, mxID(_toPrecision), XS_DONT_ENUM_FLAG);
57
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toString), 1, mxID(_toString), XS_DONT_ENUM_FLAG);
58
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG);
59
31.0k
  mxNumberPrototype = *the->stack;
60
31.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Number), 1, mxID(_Number));
61
31.0k
  mxNumberConstructor = *the->stack;
62
31.0k
  slot = fxLastProperty(the, slot);
63
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isFinite), 1, mxID(_isFinite), XS_DONT_ENUM_FLAG);
64
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isInteger), 1, mxID(_isInteger), XS_DONT_ENUM_FLAG);
65
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isNaN), 1, mxID(_isNaN), XS_DONT_ENUM_FLAG);
66
31.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isSafeInteger), 1, mxID(_isSafeInteger), XS_DONT_ENUM_FLAG);
67
31.0k
  slot = fxNextSlotProperty(the, slot, &mxParseFloatFunction, mxID(_parseFloat), XS_DONT_ENUM_FLAG);
68
31.0k
  slot = fxNextSlotProperty(the, slot, &mxParseIntFunction, mxID(_parseInt), XS_DONT_ENUM_FLAG);
69
31.0k
  slot = fxNextNumberProperty(the, slot, C_EPSILON, mxID(_EPSILON), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
70
31.0k
  slot = fxNextNumberProperty(the, slot, C_MAX_SAFE_INTEGER, mxID(_MAX_SAFE_INTEGER), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
71
31.0k
  slot = fxNextNumberProperty(the, slot, C_DBL_MAX, mxID(_MAX_VALUE), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
72
31.0k
  slot = fxNextNumberProperty(the, slot, C_MIN_SAFE_INTEGER, mxID(_MIN_SAFE_INTEGER), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
73
31.0k
  slot = fxNextNumberProperty(the, slot, C_DBL_MIN, mxID(_MIN_VALUE), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
74
31.0k
  slot = fxNextNumberProperty(the, slot, C_NAN, mxID(_NaN), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
75
31.0k
  slot = fxNextNumberProperty(the, slot, -((txNumber)C_INFINITY), mxID(_NEGATIVE_INFINITY), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
76
31.0k
  slot = fxNextNumberProperty(the, slot, (txNumber)C_INFINITY, mxID(_POSITIVE_INFINITY), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
77
31.0k
  mxPop();
78
31.0k
}
79
80
txSlot* fxNewNumberInstance(txMachine* the)
81
12.1M
{
82
12.1M
  txSlot* instance;
83
12.1M
  instance = fxNewObjectInstance(the);
84
12.1M
  fxNextNumberProperty(the, instance, 0, XS_NO_ID, XS_INTERNAL_FLAG);
85
12.1M
  return instance;
86
12.1M
}
87
88
void fxNumberCoerce(txMachine* the, txSlot* slot)
89
2.28k
{
90
2.28k
  fxToNumber(the, slot);
91
2.28k
}
92
93
void fx_isFinite(txMachine* the)
94
224
{
95
224
  int fpclass;
96
224
  txNumber number = (mxArgc < 1) ?  C_NAN : fxToNumber(the, mxArgv(0)); 
97
224
  mxResult->kind = XS_BOOLEAN_KIND;
98
224
    mxResult->value.boolean = 0;
99
224
  fpclass = c_fpclassify(number);
100
224
  if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE))
101
193
    mxResult->value.boolean = 1;
102
224
}
103
104
void fx_isNaN(txMachine* the)
105
4.41k
{
106
4.41k
  int fpclass;
107
4.41k
  txNumber number = (mxArgc < 1) ?  C_NAN : fxToNumber(the, mxArgv(0)); 
108
4.41k
  mxResult->kind = XS_BOOLEAN_KIND;
109
4.41k
    mxResult->value.boolean = 0;
110
4.41k
  fpclass = c_fpclassify(number);
111
4.41k
  if (fpclass == C_FP_NAN)
112
2.64k
    mxResult->value.boolean = 1;
113
4.41k
}
114
115
void fx_parseFloat(txMachine* the)
116
41.3k
{
117
41.3k
  if (mxArgc < 1) {
118
79
    mxResult->value.number = C_NAN;
119
79
    mxResult->kind = XS_NUMBER_KIND;
120
79
        return;
121
79
  }
122
41.2k
  fxToString(the, mxArgv(0));
123
41.2k
  mxResult->kind = XS_NUMBER_KIND;
124
41.2k
  mxResult->value.number = fxStringToNumber(the, mxArgv(0)->value.string, 0);
125
41.2k
}
126
127
void fx_parseInt(txMachine* the)
128
490k
{
129
490k
  txInteger aRadix, aDigit;
130
490k
  txNumber aSign, aResult;
131
490k
  txString s, r;
132
490k
  char c;
133
  
134
490k
  if (mxArgc < 1) {
135
26
    mxResult->value.number = C_NAN;
136
26
    mxResult->kind = XS_NUMBER_KIND;
137
26
        return;
138
26
  }
139
490k
  fxToString(the, mxArgv(0));
140
490k
  if (mxArgc > 1) {
141
485k
    aRadix = fxToInteger(the, mxArgv(1));
142
485k
    if (aRadix) {
143
365k
      if ((aRadix < 2) || (36 < aRadix)) {
144
49.1k
        mxResult->kind = XS_NUMBER_KIND;
145
49.1k
        mxResult->value.number = C_NAN;
146
49.1k
        return;
147
49.1k
      }
148
365k
    }
149
485k
  }
150
4.49k
  else
151
4.49k
    aRadix = 0;
152
441k
  s = fxSkipSpaces(mxArgv(0)->value.string);
153
441k
  c = *s;
154
441k
  aSign = 1;
155
441k
  if (c == '+')
156
926
    s++;
157
440k
  else if (c == '-') {
158
1.19k
    s++;
159
1.19k
    aSign = -1;
160
1.19k
  }
161
441k
  if ((*s == '0') && ((*(s + 1) == 'x') || (*(s + 1) == 'X'))) {
162
939
    if ((aRadix == 0) || (aRadix == 16)) {
163
938
      aRadix = 16;
164
938
      s += 2;
165
938
    }
166
939
  }
167
  /*if (*s == '0') {
168
    if ((aRadix == 0) || (aRadix == 8)) {
169
      aRadix = 8;
170
    }
171
  }*/
172
441k
  if (aRadix == 0)
173
124k
    aRadix = 10;
174
441k
  aResult = 0;
175
441k
  r = s;
176
525k
  while ((c = *s)) {
177
188k
    if (('0' <= c) && (c <= '9'))
178
53.1k
      aDigit = c - '0';
179
135k
    else if (('a' <= c) && (c <= 'z'))
180
3.15k
      aDigit = 10 + c - 'a';
181
132k
    else if (('A' <= c) && (c <= 'Z'))
182
30.6k
      aDigit = 10 + c - 'A';
183
101k
    else
184
101k
      break;
185
87.0k
    if (aDigit >= aRadix)
186
2.56k
      break;
187
84.4k
    aResult = (aResult * aRadix) + aDigit;
188
84.4k
    s++;
189
84.4k
  }
190
441k
  if (r == s) {
191
408k
    mxResult->kind = XS_NUMBER_KIND;
192
408k
    mxResult->value.number = C_NAN;
193
408k
  }
194
32.4k
  else {
195
32.4k
    aResult *= aSign;
196
32.4k
    aRadix = (txInteger)aResult;
197
32.4k
    aSign = aRadix;
198
32.4k
    if (aSign == aResult) {
199
31.5k
      mxResult->value.integer = aRadix;
200
31.5k
      mxResult->kind = XS_INTEGER_KIND;
201
31.5k
    }
202
909
    else {
203
909
      mxResult->value.number = aResult;
204
909
      mxResult->kind = XS_NUMBER_KIND;
205
909
    }
206
32.4k
  }
207
441k
}
208
209
void fx_Number(txMachine* the)
210
245k
{
211
245k
  txNumber value = 0;
212
245k
  if (mxArgc > 0) {
213
132k
    txSlot* slot = mxArgv(0);
214
132k
    if (slot->kind == XS_REFERENCE_KIND)
215
1.58k
      fxToPrimitive(the, slot, XS_NUMBER_HINT);
216
132k
    if ((slot->kind == XS_BIGINT_KIND) || (slot->kind == XS_BIGINT_X_KIND))
217
408
      value = fxBigIntToNumber(the, slot);
218
132k
    else
219
132k
      value = fxToNumber(the, slot);
220
132k
  }
221
245k
  if (mxIsUndefined(mxTarget)) {
222
245k
        mxResult->kind = XS_NUMBER_KIND;
223
245k
        mxResult->value.number = value;
224
245k
        fx_Math_toInteger(the);
225
245k
  }
226
425
  else {
227
425
    txSlot* instance;
228
425
    mxPushSlot(mxTarget);
229
425
    fxGetPrototypeFromConstructor(the, &mxNumberPrototype);
230
425
    instance = fxNewNumberInstance(the);
231
425
    instance->next->value.number = value;
232
425
    mxPullSlot(mxResult);
233
425
  }
234
245k
}
235
236
void fx_Number_isFinite(txMachine* the)
237
64
{
238
64
  int fpclass;
239
64
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
240
64
  mxResult->kind = XS_BOOLEAN_KIND;
241
64
    mxResult->value.boolean = 0;
242
64
    if (slot) {
243
63
      if (slot->kind == XS_INTEGER_KIND)
244
19
      mxResult->value.boolean = 1;
245
44
      else if (slot->kind == XS_NUMBER_KIND) {
246
26
      fpclass = c_fpclassify(slot->value.number);
247
26
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE))
248
16
        mxResult->value.boolean = 1;
249
26
    }
250
63
  }
251
64
}
252
253
void fx_Number_isInteger(txMachine* the)
254
96
{
255
96
  int fpclass;
256
96
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
257
96
  mxResult->kind = XS_BOOLEAN_KIND;
258
96
    mxResult->value.boolean = 0;
259
96
    if (slot) {
260
93
      if (slot->kind == XS_INTEGER_KIND)
261
49
      mxResult->value.boolean = 1;
262
44
      else if (slot->kind == XS_NUMBER_KIND) {
263
23
      fpclass = c_fpclassify(slot->value.number);
264
23
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE)) {
265
19
        txNumber check = c_trunc(slot->value.number);
266
19
        if (slot->value.number == check)
267
9
          mxResult->value.boolean = 1;
268
19
      }
269
23
    }
270
93
  }
271
96
}
272
273
void fx_Number_isNaN(txMachine* the)
274
109
{
275
109
  int fpclass;
276
109
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
277
109
  mxResult->kind = XS_BOOLEAN_KIND;
278
109
    mxResult->value.boolean = 0;
279
109
    if (slot) {
280
108
      if (slot->kind == XS_NUMBER_KIND) {
281
27
      fpclass = c_fpclassify(slot->value.number);
282
27
      if (fpclass == C_FP_NAN)
283
10
        mxResult->value.boolean = 1;
284
27
    }
285
108
  }
286
109
}
287
288
void fx_Number_isSafeInteger(txMachine* the)
289
3.89k
{
290
3.89k
  int fpclass;
291
3.89k
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
292
3.89k
  mxResult->kind = XS_BOOLEAN_KIND;
293
3.89k
    mxResult->value.boolean = 0;
294
3.89k
    if (slot) {
295
3.89k
      if (slot->kind == XS_INTEGER_KIND)
296
7
      mxResult->value.boolean = 1;
297
3.88k
      else if (slot->kind == XS_NUMBER_KIND) {
298
25
      fpclass = c_fpclassify(slot->value.number);
299
25
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE)) {
300
21
        txNumber check = c_trunc(slot->value.number);
301
21
        if (slot->value.number == check) {
302
11
          if ((C_MIN_SAFE_INTEGER <= check) && (check <= C_MAX_SAFE_INTEGER))
303
4
            mxResult->value.boolean = 1;
304
11
        }
305
21
      }
306
25
    }
307
3.89k
  }
308
3.89k
}
309
310
void fx_Number_prototype_toExponential(txMachine* the)
311
71.4k
{
312
71.4k
  char buffer[256];
313
71.4k
  txInteger mode = 0;
314
71.4k
  txNumber precision = 0;
315
71.4k
  txNumber value;
316
71.4k
  txSlot* slot = fxCheckNumber(the, mxThis);
317
71.4k
  if (!slot) mxTypeError("this: not a number");
318
71.4k
  value = slot->value.number;
319
71.4k
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
320
71.4k
    precision = fxToNumber(the, mxArgv(0));
321
71.4k
    if (c_isnan(precision))
322
2
      precision = 0;
323
71.4k
    else if (c_isfinite(precision))
324
71.4k
      precision = c_trunc(precision);
325
71.4k
  }
326
19
  else
327
19
    precision = 0;
328
71.4k
  if (c_isnan(value))
329
5
    precision = 0;
330
71.4k
  else if (c_isfinite(value)) {
331
177
    if ((precision < 0) || (100 < precision))
332
4
      mxRangeError("invalid fractionDigits");
333
173
    if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0)))
334
154
      precision++;
335
173
    mode = 'e';
336
173
  }
337
71.2k
  else
338
71.2k
    precision = 0;
339
71.4k
  fxNumberToString(the, slot->value.number, buffer, sizeof(buffer), mode, (int)precision);
340
71.4k
  fxCopyStringC(the, mxResult, buffer);
341
71.4k
}
342
343
void fx_Number_prototype_toFixed(txMachine* the)
344
186k
{
345
186k
  char buffer[256];
346
186k
  txInteger mode = 0;
347
186k
  txNumber precision = 0;
348
186k
  txNumber value;
349
186k
  txSlot* slot = fxCheckNumber(the, mxThis);
350
186k
  if (!slot) mxTypeError("this: not a number");
351
186k
  value = slot->value.number;
352
186k
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
353
167k
    precision = fxToNumber(the, mxArgv(0));
354
167k
    if (c_isnan(precision))
355
50.4k
      precision = 0;
356
116k
    else if (c_isfinite(precision))
357
116k
      precision = c_trunc(precision);
358
167k
  }
359
19.0k
  else
360
19.0k
    precision = 0;
361
186k
  if ((precision < 0) || (100 < precision))
362
7
    mxRangeError("invalid fractionDigits");
363
186k
  if (c_fabs(value) >= 1e21)
364
688
    precision = 0;
365
185k
  else
366
185k
    mode = 'f';
367
186k
  fxNumberToString(the, value, buffer, sizeof(buffer), mode, (int)precision);
368
186k
  fxCopyStringC(the, mxResult, buffer);
369
186k
}
370
371
void fx_Number_prototype_toLocaleString(txMachine* the)
372
7
{
373
7
  txSlot* slot = fxCheckNumber(the, mxThis);
374
7
  if (!slot) mxTypeError("this: not a number");
375
7
  mxResult->kind = slot->kind;
376
7
  mxResult->value = slot->value;
377
7
  fxToString(the, mxResult);
378
7
}
379
380
void fx_Number_prototype_toPrecision(txMachine* the)
381
893k
{
382
893k
  char buffer[256];
383
893k
  txInteger mode = 0;
384
893k
  txNumber precision = 0;
385
893k
  txNumber value;
386
893k
  txSlot* slot = fxCheckNumber(the, mxThis);
387
893k
  if (!slot) mxTypeError("this: not a number");
388
893k
  value = slot->value.number;
389
893k
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
390
893k
    precision = fxToNumber(the, mxArgv(0));
391
893k
    if (c_isnan(precision))
392
4
      precision = 0;
393
893k
    else if (c_isfinite(precision))
394
893k
      precision = c_trunc(precision);
395
893k
    if (c_isnan(value))
396
86.0k
      precision = 0;
397
807k
    else if (c_isfinite(value)) {
398
754k
      if ((precision < 1) || (100 < precision))
399
9
        mxRangeError("invalid precision");
400
754k
      mode = 'g';
401
754k
    }
402
52.7k
    else
403
52.7k
      precision = 0;
404
893k
  }
405
893k
  fxNumberToString(the, value, buffer, sizeof(buffer), mode, (int)precision);
406
893k
  fxCopyStringC(the, mxResult, buffer);
407
893k
}
408
409
void fx_Number_prototype_toString(txMachine* the)
410
696k
{
411
696k
  txInteger radix;
412
696k
  txSlot* slot = fxCheckNumber(the, mxThis);
413
696k
  if (!slot) mxTypeError("this: not a number");
414
696k
  if ((mxArgc > 0) && (!mxIsUndefined(mxArgv(0)))) {
415
694k
    radix = fxToInteger(the, mxArgv(0));
416
694k
    if ((radix < 2) || (36 < radix))
417
581
      mxRangeError("invalid radix");
418
694k
  }
419
2.67k
  else  
420
2.67k
    radix = 10;
421
696k
  mxResult->kind = slot->kind;
422
696k
  mxResult->value = slot->value;
423
696k
  if (radix == 10)
424
2.67k
    fxToString(the, mxResult);
425
693k
  else {
426
693k
    txNumber value = mxResult->value.number;
427
693k
    switch (c_fpclassify(value)) {
428
392k
    case C_FP_INFINITE:
429
392k
      if (value < 0)
430
392k
        fxStringX(the, mxResult, "-Infinity");
431
489
      else
432
489
        fxStringX(the, mxResult, "Infinity");
433
392k
      break;
434
233
    case C_FP_NAN:
435
233
      fxStringX(the, mxResult, "NaN");
436
233
      break;
437
126k
    case C_FP_ZERO:
438
126k
      fxStringX(the, mxResult, "0");
439
126k
      break;
440
174k
    default: {
441
      // Thanks Google V8 for the fraction part
442
174k
      static const char gxDigits[] ICACHE_FLASH_ATTR = "0123456789abcdefghijklmnopqrstuvwxyz";
443
174k
      txInteger minus;
444
174k
      txNumber integer;
445
174k
      txNumber fraction;
446
174k
      txNumber next;
447
174k
      txU8* nextCast = (txU8*)&next;
448
174k
      txNumber delta;
449
174k
      txSize length;
450
174k
      txString string;
451
174k
      txNumber modulo;
452
174k
      if (value < 0) {
453
21.1k
        minus = 1;
454
21.1k
        value = -value;
455
21.1k
      } 
456
152k
      else
457
152k
        minus = 0;
458
174k
      integer = c_floor(value);
459
174k
      fraction = value - integer;
460
174k
      next = value;
461
174k
      *nextCast = *nextCast + 1;
462
174k
      delta = 0.5 * (next - value);
463
174k
      next = 0;
464
174k
      *nextCast = *nextCast + 1;
465
174k
      if (delta < next)
466
0
        delta = next;
467
174k
      length = minus + ((integer)? (txSize)c_round(c_log1p(integer) / c_log(radix)) : 0) + 1;
468
174k
      if (fraction >= delta) {
469
695k
        #define mxFractionPartLength 2048
470
22.2k
        txString dot;
471
22.2k
        txInteger i = 0;
472
22.2k
        txInteger digit;
473
22.2k
        string = mxResult->value.string = fxNewChunk(the, length + 1 + mxFractionPartLength + 1);
474
22.2k
        dot = string + length;
475
22.2k
        dot[i++] = '.';
476
695k
        do {
477
695k
          fraction *= radix;
478
695k
          delta *= radix;
479
695k
          digit = (txInteger)fraction;
480
695k
          dot[i++] = c_read8(gxDigits + digit);
481
695k
          fraction -= digit;
482
695k
          if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
483
261k
            if (fraction + delta > 1) {
484
3.61k
              for (;;) {
485
3.61k
                char c;
486
3.61k
                i--;
487
3.61k
                if (i == 0) {
488
0
                  integer += 1;
489
0
                  break;
490
0
                }
491
3.61k
                c = dot[i];
492
3.61k
                digit = c > '9' ? (c - 'a' + 10) : (c - '0');
493
3.61k
                if (digit + 1 < radix) {
494
3.53k
                  dot[i++] = c_read8(gxDigits + digit + 1);
495
3.53k
                  break;
496
3.53k
                }
497
3.61k
              }
498
3.53k
              break;
499
3.53k
            }
500
261k
          }
501
695k
        } while ((fraction >= delta) && (i < mxFractionPartLength));
502
22.2k
        dot[i++] = 0;
503
22.2k
        length += i;
504
22.2k
        string = dot;
505
22.2k
      }
506
151k
      else {
507
151k
        length += 1;
508
151k
        string = mxResult->value.string = fxNewChunk(the, length);
509
151k
        string += length;
510
151k
        *(--string) = 0;
511
151k
      }
512
174k
      modulo = C_MAX_SAFE_INTEGER * radix;
513
51.1M
      while (integer > modulo) {
514
50.9M
        *(--string) = '0';
515
50.9M
        integer = integer / radix;
516
50.9M
      }
517
5.34M
      do {
518
5.34M
        modulo = c_fmod(integer, radix);
519
5.34M
        *(--string) = c_read8(gxDigits + (txInteger)modulo);
520
5.34M
        integer = (integer - modulo) / radix;
521
5.34M
      } while (integer >= 1);
522
174k
      if (minus) {
523
21.1k
        *(--string) = '-';
524
21.1k
      }
525
174k
      minus = (txInteger)(string - mxResult->value.string);
526
174k
      if (minus > 0) {
527
16.9k
        length -= minus;
528
16.9k
        c_memmove(mxResult->value.string, string, length);
529
16.9k
      }
530
174k
      mxResult->value.string = fxRenewChunk(the, mxResult->value.string, length);
531
174k
      mxResult->kind = XS_STRING_KIND;
532
174k
    }}
533
693k
  }
534
696k
}
535
536
void fx_Number_prototype_valueOf(txMachine* the)
537
172k
{
538
172k
  txSlot* slot = fxCheckNumber(the, mxThis);
539
172k
  if (!slot) mxTypeError("this: not a number");
540
172k
  mxResult->kind = slot->kind;
541
172k
  mxResult->value = slot->value;
542
172k
}
543
544
txSlot* fxCheckNumber(txMachine* the, txSlot* it)
545
2.02M
{
546
2.02M
  txSlot* result = C_NULL;
547
2.02M
  if (it->kind == XS_INTEGER_KIND) {
548
263k
    fxToNumber(the, it);
549
263k
    result = it;
550
263k
  }
551
1.75M
  else if (it->kind == XS_NUMBER_KIND)
552
1.58M
    result = it;
553
174k
  else if (it->kind == XS_REFERENCE_KIND) {
554
174k
    txSlot* instance = it->value.reference;
555
174k
    it = instance->next;
556
174k
    if ((it) && (it->flag & XS_INTERNAL_FLAG) && (it->kind == XS_NUMBER_KIND))
557
174k
      result = it;
558
174k
  }
559
2.02M
  return result;
560
2.02M
}