Coverage Report

Created: 2025-06-13 06:10

/src/moddable/xs/sources/xsNumber.c
Line
Count
Source (jump to first uncovered line)
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
6.57k
{
44
6.57k
  txSlot* slot;
45
  
46
6.57k
  mxPushNumber((txNumber)C_INFINITY);
47
6.57k
  mxPull(mxInfinity);
48
6.57k
  mxPushNumber((txNumber)C_NAN);
49
6.57k
  mxPull(mxNaN);
50
51
6.57k
  mxPush(mxObjectPrototype);
52
6.57k
  slot = fxLastProperty(the, fxNewNumberInstance(the));
53
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toExponential), 1, mxID(_toExponential), XS_DONT_ENUM_FLAG);
54
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toFixed), 1, mxID(_toFixed), XS_DONT_ENUM_FLAG);
55
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
56
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toPrecision), 1, mxID(_toPrecision), XS_DONT_ENUM_FLAG);
57
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_toString), 1, mxID(_toString), XS_DONT_ENUM_FLAG);
58
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG);
59
6.57k
  mxNumberPrototype = *the->stack;
60
6.57k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Number), 1, mxID(_Number));
61
6.57k
  mxNumberConstructor = *the->stack;
62
6.57k
  slot = fxLastProperty(the, slot);
63
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isFinite), 1, mxID(_isFinite), XS_DONT_ENUM_FLAG);
64
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isInteger), 1, mxID(_isInteger), XS_DONT_ENUM_FLAG);
65
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isNaN), 1, mxID(_isNaN), XS_DONT_ENUM_FLAG);
66
6.57k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Number_isSafeInteger), 1, mxID(_isSafeInteger), XS_DONT_ENUM_FLAG);
67
6.57k
  slot = fxNextSlotProperty(the, slot, &mxParseFloatFunction, mxID(_parseFloat), XS_DONT_ENUM_FLAG);
68
6.57k
  slot = fxNextSlotProperty(the, slot, &mxParseIntFunction, mxID(_parseInt), XS_DONT_ENUM_FLAG);
69
6.57k
  slot = fxNextNumberProperty(the, slot, C_EPSILON, mxID(_EPSILON), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
70
6.57k
  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
6.57k
  slot = fxNextNumberProperty(the, slot, C_DBL_MAX, mxID(_MAX_VALUE), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
72
6.57k
  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
6.57k
  slot = fxNextNumberProperty(the, slot, C_DBL_MIN, mxID(_MIN_VALUE), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
74
6.57k
  slot = fxNextNumberProperty(the, slot, C_NAN, mxID(_NaN), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
75
6.57k
  slot = fxNextNumberProperty(the, slot, -((txNumber)C_INFINITY), mxID(_NEGATIVE_INFINITY), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
76
6.57k
  slot = fxNextNumberProperty(the, slot, (txNumber)C_INFINITY, mxID(_POSITIVE_INFINITY), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
77
6.57k
  mxPop();
78
6.57k
}
79
80
txSlot* fxNewNumberInstance(txMachine* the)
81
6.57k
{
82
6.57k
  txSlot* instance;
83
6.57k
  instance = fxNewObjectInstance(the);
84
6.57k
  fxNextNumberProperty(the, instance, 0, XS_NO_ID, XS_INTERNAL_FLAG);
85
6.57k
  return instance;
86
6.57k
}
87
88
void fxNumberCoerce(txMachine* the, txSlot* slot)
89
0
{
90
0
  fxToNumber(the, slot);
91
0
}
92
93
void fx_isFinite(txMachine* the)
94
0
{
95
0
  int fpclass;
96
0
  txNumber number = (mxArgc < 1) ?  C_NAN : fxToNumber(the, mxArgv(0)); 
97
0
  mxResult->kind = XS_BOOLEAN_KIND;
98
0
    mxResult->value.boolean = 0;
99
0
  fpclass = c_fpclassify(number);
100
0
  if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE))
101
0
    mxResult->value.boolean = 1;
102
0
}
103
104
void fx_isNaN(txMachine* the)
105
0
{
106
0
  int fpclass;
107
0
  txNumber number = (mxArgc < 1) ?  C_NAN : fxToNumber(the, mxArgv(0)); 
108
0
  mxResult->kind = XS_BOOLEAN_KIND;
109
0
    mxResult->value.boolean = 0;
110
0
  fpclass = c_fpclassify(number);
111
0
  if (fpclass == C_FP_NAN)
112
0
    mxResult->value.boolean = 1;
113
0
}
114
115
void fx_parseFloat(txMachine* the)
116
0
{
117
0
  if (mxArgc < 1) {
118
0
    mxResult->value.number = C_NAN;
119
0
    mxResult->kind = XS_NUMBER_KIND;
120
0
        return;
121
0
  }
122
0
  fxToString(the, mxArgv(0));
123
0
  mxResult->kind = XS_NUMBER_KIND;
124
0
  mxResult->value.number = fxStringToNumber(the, mxArgv(0)->value.string, 0);
125
0
}
126
127
void fx_parseInt(txMachine* the)
128
0
{
129
0
  txInteger aRadix, aDigit;
130
0
  txNumber aSign, aResult;
131
0
  txString s, r;
132
0
  char c;
133
  
134
0
  if (mxArgc < 1) {
135
0
    mxResult->value.number = C_NAN;
136
0
    mxResult->kind = XS_NUMBER_KIND;
137
0
        return;
138
0
  }
139
0
  fxToString(the, mxArgv(0));
140
0
  if (mxArgc > 1) {
141
0
    aRadix = fxToInteger(the, mxArgv(1));
142
0
    if (aRadix) {
143
0
      if ((aRadix < 2) || (36 < aRadix)) {
144
0
        mxResult->kind = XS_NUMBER_KIND;
145
0
        mxResult->value.number = C_NAN;
146
0
        return;
147
0
      }
148
0
    }
149
0
  }
150
0
  else
151
0
    aRadix = 0;
152
0
  s = fxSkipSpaces(mxArgv(0)->value.string);
153
0
  c = *s;
154
0
  aSign = 1;
155
0
  if (c == '+')
156
0
    s++;
157
0
  else if (c == '-') {
158
0
    s++;
159
0
    aSign = -1;
160
0
  }
161
0
  if ((*s == '0') && ((*(s + 1) == 'x') || (*(s + 1) == 'X'))) {
162
0
    if ((aRadix == 0) || (aRadix == 16)) {
163
0
      aRadix = 16;
164
0
      s += 2;
165
0
    }
166
0
  }
167
  /*if (*s == '0') {
168
    if ((aRadix == 0) || (aRadix == 8)) {
169
      aRadix = 8;
170
    }
171
  }*/
172
0
  if (aRadix == 0)
173
0
    aRadix = 10;
174
0
  aResult = 0;
175
0
  r = s;
176
0
  while ((c = *s)) {
177
0
    if (('0' <= c) && (c <= '9'))
178
0
      aDigit = c - '0';
179
0
    else if (('a' <= c) && (c <= 'z'))
180
0
      aDigit = 10 + c - 'a';
181
0
    else if (('A' <= c) && (c <= 'Z'))
182
0
      aDigit = 10 + c - 'A';
183
0
    else
184
0
      break;
185
0
    if (aDigit >= aRadix)
186
0
      break;
187
0
    aResult = (aResult * aRadix) + aDigit;
188
0
    s++;
189
0
  }
190
0
  if (r == s) {
191
0
    mxResult->kind = XS_NUMBER_KIND;
192
0
    mxResult->value.number = C_NAN;
193
0
  }
194
0
  else {
195
0
    aResult *= aSign;
196
0
    aRadix = (txInteger)aResult;
197
0
    aSign = aRadix;
198
0
    if (aSign == aResult) {
199
0
      mxResult->value.integer = aRadix;
200
0
      mxResult->kind = XS_INTEGER_KIND;
201
0
    }
202
0
    else {
203
0
      mxResult->value.number = aResult;
204
0
      mxResult->kind = XS_NUMBER_KIND;
205
0
    }
206
0
  }
207
0
}
208
209
void fx_Number(txMachine* the)
210
0
{
211
0
  txNumber value = 0;
212
0
  if (mxArgc > 0) {
213
0
    txSlot* slot = mxArgv(0);
214
0
    if (slot->kind == XS_REFERENCE_KIND)
215
0
      fxToPrimitive(the, slot, XS_NUMBER_HINT);
216
0
    if ((slot->kind == XS_BIGINT_KIND) || (slot->kind == XS_BIGINT_X_KIND))
217
0
      value = fxBigIntToNumber(the, slot);
218
0
    else
219
0
      value = fxToNumber(the, slot);
220
0
  }
221
0
  if (mxIsUndefined(mxTarget)) {
222
0
        mxResult->kind = XS_NUMBER_KIND;
223
0
        mxResult->value.number = value;
224
0
        fx_Math_toInteger(the);
225
0
  }
226
0
  else {
227
0
    txSlot* instance;
228
0
    mxPushSlot(mxTarget);
229
0
    fxGetPrototypeFromConstructor(the, &mxNumberPrototype);
230
0
    instance = fxNewNumberInstance(the);
231
0
    instance->next->value.number = value;
232
0
    mxPullSlot(mxResult);
233
0
  }
234
0
}
235
236
void fx_Number_isFinite(txMachine* the)
237
0
{
238
0
  int fpclass;
239
0
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
240
0
  mxResult->kind = XS_BOOLEAN_KIND;
241
0
    mxResult->value.boolean = 0;
242
0
    if (slot) {
243
0
      if (slot->kind == XS_INTEGER_KIND)
244
0
      mxResult->value.boolean = 1;
245
0
      else if (slot->kind == XS_NUMBER_KIND) {
246
0
      fpclass = c_fpclassify(slot->value.number);
247
0
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE))
248
0
        mxResult->value.boolean = 1;
249
0
    }
250
0
  }
251
0
}
252
253
void fx_Number_isInteger(txMachine* the)
254
0
{
255
0
  int fpclass;
256
0
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
257
0
  mxResult->kind = XS_BOOLEAN_KIND;
258
0
    mxResult->value.boolean = 0;
259
0
    if (slot) {
260
0
      if (slot->kind == XS_INTEGER_KIND)
261
0
      mxResult->value.boolean = 1;
262
0
      else if (slot->kind == XS_NUMBER_KIND) {
263
0
      fpclass = c_fpclassify(slot->value.number);
264
0
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE)) {
265
0
        txNumber check = c_trunc(slot->value.number);
266
0
        if (slot->value.number == check)
267
0
          mxResult->value.boolean = 1;
268
0
      }
269
0
    }
270
0
  }
271
0
}
272
273
void fx_Number_isNaN(txMachine* the)
274
0
{
275
0
  int fpclass;
276
0
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
277
0
  mxResult->kind = XS_BOOLEAN_KIND;
278
0
    mxResult->value.boolean = 0;
279
0
    if (slot) {
280
0
      if (slot->kind == XS_NUMBER_KIND) {
281
0
      fpclass = c_fpclassify(slot->value.number);
282
0
      if (fpclass == C_FP_NAN)
283
0
        mxResult->value.boolean = 1;
284
0
    }
285
0
  }
286
0
}
287
288
void fx_Number_isSafeInteger(txMachine* the)
289
0
{
290
0
  int fpclass;
291
0
  txSlot* slot = (mxArgc < 1) ?  C_NULL : mxArgv(0);
292
0
  mxResult->kind = XS_BOOLEAN_KIND;
293
0
    mxResult->value.boolean = 0;
294
0
    if (slot) {
295
0
      if (slot->kind == XS_INTEGER_KIND)
296
0
      mxResult->value.boolean = 1;
297
0
      else if (slot->kind == XS_NUMBER_KIND) {
298
0
      fpclass = c_fpclassify(slot->value.number);
299
0
      if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE)) {
300
0
        txNumber check = c_trunc(slot->value.number);
301
0
        if (slot->value.number == check) {
302
0
          if ((C_MIN_SAFE_INTEGER <= check) && (check <= C_MAX_SAFE_INTEGER))
303
0
            mxResult->value.boolean = 1;
304
0
        }
305
0
      }
306
0
    }
307
0
  }
308
0
}
309
310
void fx_Number_prototype_toExponential(txMachine* the)
311
0
{
312
0
  char buffer[256];
313
0
  txInteger mode = 0;
314
0
  txNumber precision = 0;
315
0
  txNumber value;
316
0
  txSlot* slot = fxCheckNumber(the, mxThis);
317
0
  if (!slot) mxTypeError("this: not a number");
318
0
  value = slot->value.number;
319
0
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
320
0
    precision = fxToNumber(the, mxArgv(0));
321
0
    if (c_isnan(precision))
322
0
      precision = 0;
323
0
    else if (c_isfinite(precision))
324
0
      precision = c_trunc(precision);
325
0
  }
326
0
  else
327
0
    precision = 0;
328
0
  if (c_isnan(value))
329
0
    precision = 0;
330
0
  else if (c_isfinite(value)) {
331
0
    if ((precision < 0) || (100 < precision))
332
0
      mxRangeError("invalid fractionDigits");
333
0
    if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0)))
334
0
      precision++;
335
0
    mode = 'e';
336
0
  }
337
0
  else
338
0
    precision = 0;
339
0
  fxNumberToString(the, slot->value.number, buffer, sizeof(buffer), mode, (int)precision);
340
0
  fxCopyStringC(the, mxResult, buffer);
341
0
}
342
343
void fx_Number_prototype_toFixed(txMachine* the)
344
0
{
345
0
  char buffer[256];
346
0
  txInteger mode = 0;
347
0
  txNumber precision = 0;
348
0
  txNumber value;
349
0
  txSlot* slot = fxCheckNumber(the, mxThis);
350
0
  if (!slot) mxTypeError("this: not a number");
351
0
  value = slot->value.number;
352
0
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
353
0
    precision = fxToNumber(the, mxArgv(0));
354
0
    if (c_isnan(precision))
355
0
      precision = 0;
356
0
    else if (c_isfinite(precision))
357
0
      precision = c_trunc(precision);
358
0
  }
359
0
  else
360
0
    precision = 0;
361
0
  if ((precision < 0) || (100 < precision))
362
0
    mxRangeError("invalid fractionDigits");
363
0
  if (c_fabs(value) >= 1e21)
364
0
    precision = 0;
365
0
  else
366
0
    mode = 'f';
367
0
  fxNumberToString(the, value, buffer, sizeof(buffer), mode, (int)precision);
368
0
  fxCopyStringC(the, mxResult, buffer);
369
0
}
370
371
void fx_Number_prototype_toLocaleString(txMachine* the)
372
0
{
373
0
  txSlot* slot = fxCheckNumber(the, mxThis);
374
0
  if (!slot) mxTypeError("this: not a number");
375
0
  mxResult->kind = slot->kind;
376
0
  mxResult->value = slot->value;
377
0
  fxToString(the, mxResult);
378
0
}
379
380
void fx_Number_prototype_toPrecision(txMachine* the)
381
0
{
382
0
  char buffer[256];
383
0
  txInteger mode = 0;
384
0
  txNumber precision = 0;
385
0
  txNumber value;
386
0
  txSlot* slot = fxCheckNumber(the, mxThis);
387
0
  if (!slot) mxTypeError("this: not a number");
388
0
  value = slot->value.number;
389
0
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0))) {
390
0
    precision = fxToNumber(the, mxArgv(0));
391
0
    if (c_isnan(precision))
392
0
      precision = 0;
393
0
    else if (c_isfinite(precision))
394
0
      precision = c_trunc(precision);
395
0
    if (c_isnan(value))
396
0
      precision = 0;
397
0
    else if (c_isfinite(value)) {
398
0
      if ((precision < 1) || (100 < precision))
399
0
        mxRangeError("invalid precision");
400
0
      mode = 'g';
401
0
    }
402
0
    else
403
0
      precision = 0;
404
0
  }
405
0
  fxNumberToString(the, value, buffer, sizeof(buffer), mode, (int)precision);
406
0
  fxCopyStringC(the, mxResult, buffer);
407
0
}
408
409
void fx_Number_prototype_toString(txMachine* the)
410
0
{
411
0
  txInteger radix;
412
0
  txSlot* slot = fxCheckNumber(the, mxThis);
413
0
  if (!slot) mxTypeError("this: not a number");
414
0
  if ((mxArgc > 0) && (!mxIsUndefined(mxArgv(0)))) {
415
0
    radix = fxToInteger(the, mxArgv(0));
416
0
    if ((radix < 2) || (36 < radix))
417
0
      mxRangeError("invalid radix");
418
0
  }
419
0
  else  
420
0
    radix = 10;
421
0
  mxResult->kind = slot->kind;
422
0
  mxResult->value = slot->value;
423
0
  if (radix == 10)
424
0
    fxToString(the, mxResult);
425
0
  else {
426
0
    txNumber value = mxResult->value.number;
427
0
    switch (c_fpclassify(value)) {
428
0
    case C_FP_INFINITE:
429
0
      if (value < 0)
430
0
        fxStringX(the, mxResult, "-Infinity");
431
0
      else
432
0
        fxStringX(the, mxResult, "Infinity");
433
0
      break;
434
0
    case C_FP_NAN:
435
0
      fxStringX(the, mxResult, "NaN");
436
0
      break;
437
0
    case C_FP_ZERO:
438
0
      fxStringX(the, mxResult, "0");
439
0
      break;
440
0
    default: {
441
      // Thanks Google V8 for the fraction part
442
0
      static const char gxDigits[] ICACHE_FLASH_ATTR = "0123456789abcdefghijklmnopqrstuvwxyz";
443
0
      txInteger minus;
444
0
      txNumber integer;
445
0
      txNumber fraction;
446
0
      txNumber next;
447
0
      txU8* nextCast = (txU8*)&next;
448
0
      txNumber delta;
449
0
      txSize length;
450
0
      txString string;
451
0
      txNumber modulo;
452
0
      if (value < 0) {
453
0
        minus = 1;
454
0
        value = -value;
455
0
      } 
456
0
      else
457
0
        minus = 0;
458
0
      integer = c_floor(value);
459
0
      fraction = value - integer;
460
0
      next = value;
461
0
      *nextCast = *nextCast + 1;
462
0
      delta = 0.5 * (next - value);
463
0
      next = 0;
464
0
      *nextCast = *nextCast + 1;
465
0
      if (delta < next)
466
0
        delta = next;
467
0
      length = minus + ((integer)? (txSize)c_round(c_log1p(integer) / c_log(radix)) : 0) + 1;
468
0
      if (fraction >= delta) {
469
0
        #define mxFractionPartLength 2048
470
0
        txString dot;
471
0
        txInteger i = 0;
472
0
        txInteger digit;
473
0
        string = mxResult->value.string = fxNewChunk(the, length + 1 + mxFractionPartLength + 1);
474
0
        dot = string + length;
475
0
        dot[i++] = '.';
476
0
        do {
477
0
          fraction *= radix;
478
0
          delta *= radix;
479
0
          digit = (txInteger)fraction;
480
0
          dot[i++] = c_read8(gxDigits + digit);
481
0
          fraction -= digit;
482
0
          if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
483
0
            if (fraction + delta > 1) {
484
0
              for (;;) {
485
0
                char c;
486
0
                i--;
487
0
                if (i == 0) {
488
0
                  integer += 1;
489
0
                  break;
490
0
                }
491
0
                c = dot[i];
492
0
                digit = c > '9' ? (c - 'a' + 10) : (c - '0');
493
0
                if (digit + 1 < radix) {
494
0
                  dot[i++] = c_read8(gxDigits + digit + 1);
495
0
                  break;
496
0
                }
497
0
              }
498
0
              break;
499
0
            }
500
0
          }
501
0
        } while ((fraction >= delta) && (i < mxFractionPartLength));
502
0
        dot[i++] = 0;
503
0
        length += i;
504
0
        string = dot;
505
0
      }
506
0
      else {
507
0
        length += 1;
508
0
        string = mxResult->value.string = fxNewChunk(the, length);
509
0
        string += length;
510
0
        *(--string) = 0;
511
0
      }
512
0
      modulo = C_MAX_SAFE_INTEGER * radix;
513
0
      while (integer > modulo) {
514
0
        *(--string) = '0';
515
0
        integer = integer / radix;
516
0
      }
517
0
      do {
518
0
        modulo = c_fmod(integer, radix);
519
0
        *(--string) = c_read8(gxDigits + (txInteger)modulo);
520
0
        integer = (integer - modulo) / radix;
521
0
      } while (integer >= 1);
522
0
      if (minus) {
523
0
        *(--string) = '-';
524
0
      }
525
0
      minus = (txInteger)(string - mxResult->value.string);
526
0
      if (minus > 0) {
527
0
        length -= minus;
528
0
        c_memmove(mxResult->value.string, string, length);
529
0
      }
530
0
      mxResult->value.string = fxRenewChunk(the, mxResult->value.string, length);
531
0
      mxResult->kind = XS_STRING_KIND;
532
0
    }}
533
0
  }
534
0
}
535
536
void fx_Number_prototype_valueOf(txMachine* the)
537
0
{
538
0
  txSlot* slot = fxCheckNumber(the, mxThis);
539
0
  if (!slot) mxTypeError("this: not a number");
540
0
  mxResult->kind = slot->kind;
541
0
  mxResult->value = slot->value;
542
0
}
543
544
txSlot* fxCheckNumber(txMachine* the, txSlot* it)
545
0
{
546
0
  txSlot* result = C_NULL;
547
0
  if (it->kind == XS_INTEGER_KIND) {
548
0
    fxToNumber(the, it);
549
0
    result = it;
550
0
  }
551
0
  else if (it->kind == XS_NUMBER_KIND)
552
0
    result = it;
553
0
  else if (it->kind == XS_REFERENCE_KIND) {
554
0
    txSlot* instance = it->value.reference;
555
0
    it = instance->next;
556
0
    if ((it) && (it->flag & XS_INTERNAL_FLAG) && (it->kind == XS_NUMBER_KIND))
557
0
      result = it;
558
0
  }
559
0
  return result;
560
0
}