Coverage Report

Created: 2026-11-12 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsMath.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
#include "xsum.c"
41
42
void fxBuildMath(txMachine* the)
43
30.4k
{
44
30.4k
  txSlot* slot;
45
30.4k
  mxPush(mxObjectPrototype);
46
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
47
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_abs), 1, mxID(_abs), XS_DONT_ENUM_FLAG);
48
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_acos), 1, mxID(_acos), XS_DONT_ENUM_FLAG);
49
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_acosh), 1, mxID(_acosh), XS_DONT_ENUM_FLAG);
50
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_asin), 1, mxID(_asin), XS_DONT_ENUM_FLAG);
51
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_asinh), 1, mxID(_asinh), XS_DONT_ENUM_FLAG);
52
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_atan), 1, mxID(_atan), XS_DONT_ENUM_FLAG);
53
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_atanh), 1, mxID(_atanh), XS_DONT_ENUM_FLAG);
54
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_atan2), 2, mxID(_atan2), XS_DONT_ENUM_FLAG);
55
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_cbrt), 1, mxID(_cbrt), XS_DONT_ENUM_FLAG);
56
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_ceil), 1, mxID(_ceil), XS_DONT_ENUM_FLAG);
57
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_clz32), 1, mxID(_clz32), XS_DONT_ENUM_FLAG);
58
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_cos), 1, mxID(_cos), XS_DONT_ENUM_FLAG);
59
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_cosh), 1, mxID(_cosh), XS_DONT_ENUM_FLAG);
60
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_exp), 1, mxID(_exp), XS_DONT_ENUM_FLAG);
61
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_expm1), 1, mxID(_expm1), XS_DONT_ENUM_FLAG);
62
30.4k
#if mxFloat16
63
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_f16round), 1, mxID(_f16round), XS_DONT_ENUM_FLAG);
64
30.4k
#endif
65
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_floor), 1, mxID(_floor), XS_DONT_ENUM_FLAG);
66
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_fround), 1, mxID(_fround), XS_DONT_ENUM_FLAG);
67
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_hypot), 2, mxID(_hypot_), XS_DONT_ENUM_FLAG);
68
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_idiv), 2, mxID(_idiv), XS_DONT_ENUM_FLAG);
69
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_idivmod), 2, mxID(_idivmod), XS_DONT_ENUM_FLAG);
70
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_imod), 2, mxID(_imod), XS_DONT_ENUM_FLAG);
71
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_imul), 2, mxID(_imul), XS_DONT_ENUM_FLAG);
72
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_imuldiv), 2, mxID(_imuldiv), XS_DONT_ENUM_FLAG);
73
30.4k
#if mxECMAScript2023
74
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_irandom), 0, mxID(_irandom), XS_DONT_ENUM_FLAG);
75
30.4k
#endif
76
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_irem), 2, mxID(_irem), XS_DONT_ENUM_FLAG);
77
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_log), 1, mxID(_log), XS_DONT_ENUM_FLAG);
78
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_log1p), 1, mxID(_log1p), XS_DONT_ENUM_FLAG);
79
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_log10), 1, mxID(_log10), XS_DONT_ENUM_FLAG);
80
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_log2), 1, mxID(_log2), XS_DONT_ENUM_FLAG);
81
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_max), 2, mxID(_max), XS_DONT_ENUM_FLAG);
82
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_min), 2, mxID(_min), XS_DONT_ENUM_FLAG);
83
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_mod), 2, mxID(_mod), XS_DONT_ENUM_FLAG);
84
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_pow), 2, mxID(_pow), XS_DONT_ENUM_FLAG);
85
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_random), 0, mxID(_random), XS_DONT_ENUM_FLAG);
86
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_round), 1, mxID(_round), XS_DONT_ENUM_FLAG);
87
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_sign), 1, mxID(_sign), XS_DONT_ENUM_FLAG);
88
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_sin), 1, mxID(_sin), XS_DONT_ENUM_FLAG);
89
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_sinh), 1, mxID(_sinh), XS_DONT_ENUM_FLAG);
90
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_sqrt), 1, mxID(_sqrt), XS_DONT_ENUM_FLAG);
91
30.4k
#if mxECMAScript2026
92
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_sumPrecise), 1, mxID(_sumPrecise), XS_DONT_ENUM_FLAG);
93
30.4k
#endif
94
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_tan), 1, mxID(_tan), XS_DONT_ENUM_FLAG);
95
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_tanh), 1, mxID(_tanh), XS_DONT_ENUM_FLAG);
96
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Math_trunc), 1, mxID(_trunc), XS_DONT_ENUM_FLAG);
97
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_E, mxID(_E), XS_GET_ONLY);
98
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_LN10, mxID(_LN10), XS_GET_ONLY);
99
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_LN2, mxID(_LN2), XS_GET_ONLY);
100
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_LOG10E, mxID(_LOG10E), XS_GET_ONLY);
101
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_LOG2E, mxID(_LOG2E), XS_GET_ONLY);
102
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_PI, mxID(_PI), XS_GET_ONLY);
103
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_SQRT1_2, mxID(_SQRT1_2), XS_GET_ONLY);
104
30.4k
  slot = fxNextNumberProperty(the, slot, C_M_SQRT2, mxID(_SQRT2), XS_GET_ONLY);
105
30.4k
  slot = fxNextStringXProperty(the, slot, "Math", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
106
30.4k
  mxPull(mxMathObject);
107
//@@  c_srand((unsigned)c_time(0));
108
30.4k
}
109
110
#define mxNanResultIfNoArg \
111
2.50M
  if (mxArgc < 1) {  \
112
11.3k
    mxResult->kind = XS_NUMBER_KIND; \
113
11.3k
    mxResult->value.number = C_NAN; \
114
11.3k
    return; \
115
11.3k
  }
116
117
#define mxNanResultIfNoArg2 \
118
1.21M
  if (mxArgc < 2) {  \
119
56.7k
    mxResult->kind = XS_NUMBER_KIND; \
120
56.7k
    mxResult->value.number = C_NAN; \
121
56.7k
    return; \
122
56.7k
  }
123
124
void fx_Math_abs(txMachine* the)
125
14
{
126
14
  mxNanResultIfNoArg;
127
14
  fxToNumber(the, mxArgv(0));
128
14
  mxResult->kind = XS_NUMBER_KIND;
129
14
  mxResult->value.number = c_fabs(mxArgv(0)->value.number);
130
14
}
131
132
void fx_Math_acos(txMachine* the)
133
5.58k
{
134
5.58k
  mxNanResultIfNoArg;
135
5.14k
  fxToNumber(the, mxArgv(0));
136
5.14k
  mxResult->kind = XS_NUMBER_KIND;
137
5.14k
  mxResult->value.number = c_acos(mxArgv(0)->value.number);
138
5.14k
}
139
140
void fx_Math_acosh(txMachine* the)
141
6.39k
{
142
6.39k
  mxNanResultIfNoArg;
143
5.58k
  fxToNumber(the, mxArgv(0));
144
5.58k
  mxResult->kind = XS_NUMBER_KIND;
145
5.58k
  mxResult->value.number = c_acosh(mxArgv(0)->value.number);
146
5.58k
}
147
148
void fx_Math_asin(txMachine* the)
149
6.82k
{
150
6.82k
  mxNanResultIfNoArg;
151
6.33k
  fxToNumber(the, mxArgv(0));
152
6.33k
  mxResult->kind = XS_NUMBER_KIND;
153
6.33k
  mxResult->value.number = c_asin(mxArgv(0)->value.number);
154
6.33k
}
155
156
void fx_Math_asinh(txMachine* the)
157
58.8k
{
158
58.8k
  mxNanResultIfNoArg;
159
57.5k
  fxToNumber(the, mxArgv(0));
160
57.5k
  mxResult->kind = XS_NUMBER_KIND;
161
57.5k
  mxResult->value.number = c_asinh(mxArgv(0)->value.number);
162
57.5k
}
163
164
void fx_Math_atan(txMachine* the)
165
1.00k
{
166
1.00k
  mxNanResultIfNoArg;
167
992
  fxToNumber(the, mxArgv(0));
168
992
  mxResult->kind = XS_NUMBER_KIND;
169
992
  mxResult->value.number = c_atan(mxArgv(0)->value.number);
170
992
}
171
172
void fx_Math_atanh(txMachine* the)
173
110k
{
174
110k
  mxNanResultIfNoArg;
175
109k
  fxToNumber(the, mxArgv(0));
176
109k
  mxResult->kind = XS_NUMBER_KIND;
177
109k
  mxResult->value.number = c_atanh(mxArgv(0)->value.number);
178
109k
}
179
180
void fx_Math_atan2(txMachine* the)
181
948k
{
182
948k
  mxNanResultIfNoArg;
183
948k
  fxToNumber(the, mxArgv(0));
184
948k
  mxNanResultIfNoArg2;
185
948k
  fxToNumber(the, mxArgv(1));
186
948k
  mxResult->kind = XS_NUMBER_KIND;
187
948k
  mxResult->value.number = c_atan2(mxArgv(0)->value.number, mxArgv(1)->value.number);
188
948k
}
189
190
void fx_Math_cbrt(txMachine* the)
191
24
{
192
24
  mxNanResultIfNoArg;
193
24
  fxToNumber(the, mxArgv(0));
194
24
  mxResult->kind = XS_NUMBER_KIND;
195
24
  mxResult->value.number = c_cbrt(mxArgv(0)->value.number);
196
24
}
197
198
void fx_Math_ceil(txMachine* the)
199
174k
{
200
174k
  mxNanResultIfNoArg;
201
174k
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
202
9
    mxResult->kind = XS_INTEGER_KIND;
203
9
    mxResult->value.integer = mxArgv(0)->value.integer;
204
9
    return;
205
9
  }
206
174k
  fxToNumber(the, mxArgv(0));
207
174k
  mxResult->kind = XS_NUMBER_KIND;
208
174k
  mxResult->value.number = c_ceil(mxArgv(0)->value.number);
209
174k
  fx_Math_toInteger(the);
210
174k
}
211
212
void fx_Math_clz32(txMachine* the)
213
48
{
214
48
  txUnsigned x = (mxArgc > 0) ? fxToUnsigned(the, mxArgv(0)) : 0;
215
48
  txInteger r;
216
48
  if (x)
217
#if mxWindows
218
  {
219
    _BitScanReverse(&r, x);
220
    r = 31 - r;
221
  }
222
#else
223
37
    r = __builtin_clz(x);
224
11
#endif  
225
11
  else
226
11
    r = 32;
227
48
  mxResult->kind = XS_INTEGER_KIND;
228
48
  mxResult->value.integer = r;
229
48
}
230
231
void fx_Math_cos(txMachine* the)
232
30.4k
{
233
30.4k
  mxNanResultIfNoArg;
234
30.2k
  fxToNumber(the, mxArgv(0));
235
30.2k
  mxResult->kind = XS_NUMBER_KIND;
236
30.2k
  mxResult->value.number = c_cos(mxArgv(0)->value.number);
237
30.2k
}
238
239
void fx_Math_cosh(txMachine* the)
240
13.6k
{
241
13.6k
  mxNanResultIfNoArg;
242
13.2k
  fxToNumber(the, mxArgv(0));
243
13.2k
  mxResult->kind = XS_NUMBER_KIND;
244
13.2k
  mxResult->value.number = c_cosh(mxArgv(0)->value.number);
245
13.2k
}
246
247
void fx_Math_exp(txMachine* the)
248
278k
{
249
278k
  mxNanResultIfNoArg;
250
277k
  fxToNumber(the, mxArgv(0));
251
277k
  mxResult->kind = XS_NUMBER_KIND;
252
277k
  mxResult->value.number = c_exp(mxArgv(0)->value.number);
253
277k
}
254
255
void fx_Math_expm1(txMachine* the)
256
23
{
257
23
  mxNanResultIfNoArg;
258
23
  fxToNumber(the, mxArgv(0));
259
23
  mxResult->kind = XS_NUMBER_KIND;
260
23
  mxResult->value.number = c_expm1(mxArgv(0)->value.number);
261
23
}
262
263
void fx_Math_floor(txMachine* the)
264
193k
{
265
193k
  mxNanResultIfNoArg;
266
193k
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
267
8
    mxResult->kind = XS_INTEGER_KIND;
268
8
    mxResult->value.integer = mxArgv(0)->value.integer;
269
8
    return;
270
8
  }
271
193k
  fxToNumber(the, mxArgv(0));
272
193k
  mxResult->kind = XS_NUMBER_KIND;
273
193k
  mxResult->value.number = c_floor(mxArgv(0)->value.number);
274
193k
  fx_Math_toInteger(the);
275
193k
}
276
277
void fx_Math_fround(txMachine* the)
278
114
{
279
114
  float arg;
280
114
  mxNanResultIfNoArg;
281
111
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
282
16
    mxResult->kind = XS_INTEGER_KIND;
283
16
    mxResult->value.integer = mxArgv(0)->value.integer;
284
16
    return;
285
16
  }
286
95
  arg = (float)fxToNumber(the, mxArgv(0));
287
95
  mxResult->kind = XS_NUMBER_KIND;
288
95
  mxResult->value.number = arg;
289
95
}
290
291
void fx_Math_hypot(txMachine* the)
292
26
{
293
26
  if (mxArgc == 2) {
294
16
    fxToNumber(the, mxArgv(0));
295
16
    fxToNumber(the, mxArgv(1));
296
16
    mxResult->kind = XS_NUMBER_KIND;
297
16
    mxResult->value.number = c_hypot(mxArgv(0)->value.number, mxArgv(1)->value.number);
298
16
  }
299
10
  else {
300
10
    txInteger c = mxArgc, i;
301
10
    txNumber result = 0;
302
23
    for (i = 0; i < c; i++) {
303
13
      txNumber argument = fxToNumber(the, mxArgv(i));
304
13
      result += argument * argument;
305
13
    }
306
10
    mxResult->kind = XS_NUMBER_KIND;
307
10
    mxResult->value.number = c_sqrt(result);
308
10
  }
309
26
}
310
311
void fx_Math_idiv(txMachine* the)
312
102k
{
313
102k
  txInteger x = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
314
102k
  txInteger y = (mxArgc > 1) ? fxToInteger(the, mxArgv(1)) : 0;
315
102k
  if (y == 0) {
316
102k
    mxResult->kind = XS_NUMBER_KIND;
317
102k
    mxResult->value.number = C_NAN;
318
102k
  }
319
225
  else {
320
225
    mxResult->kind = XS_INTEGER_KIND;
321
225
#if mxIntegerDivideOverflowException
322
225
    if ((x == (txInteger)0x80000000) && (y == -1))
323
4
      mxResult->value.integer = x;
324
221
    else
325
221
#endif
326
221
      mxResult->value.integer = x / y;
327
225
  }
328
102k
}
329
330
void fx_Math_idivmod(txMachine* the)
331
0
{
332
0
  mxTypeError("not available");
333
0
}
334
335
void fx_Math_imod(txMachine* the)
336
0
{
337
0
  txInteger x = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
338
0
  txInteger y = (mxArgc > 1) ? fxToInteger(the, mxArgv(1)) : 0;
339
0
  if (y == 0) {
340
0
    mxResult->kind = XS_NUMBER_KIND;
341
0
    mxResult->value.number = C_NAN;
342
0
  }
343
0
  else {
344
0
    mxResult->kind = XS_INTEGER_KIND;
345
0
#if mxIntegerDivideOverflowException
346
0
    if ((x == (txInteger)0x80000000) && (y == -1))
347
0
      mxResult->value.integer = 0;
348
0
    else
349
0
#endif
350
0
    {
351
0
      txInteger r = x % y;
352
0
      if (r && ((r ^ y) < 0))
353
0
        r += y;
354
0
      mxResult->value.integer = r;
355
0
    }
356
0
  }
357
0
}
358
359
void fx_Math_imul(txMachine* the)
360
102k
{
361
102k
  txInteger x = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
362
102k
  txInteger y = (mxArgc > 1) ? fxToInteger(the, mxArgv(1)) : 0;
363
102k
  mxResult->kind = XS_INTEGER_KIND;
364
102k
  mxResult->value.integer = (txInteger)((uint32_t)x * (uint32_t)y);
365
102k
}
366
367
void fx_Math_imuldiv(txMachine* the)
368
205k
{
369
205k
  txS8 x = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
370
205k
  txS8 y = (mxArgc > 1) ? fxToInteger(the, mxArgv(1)) : 0;
371
205k
  txS8 z = (mxArgc > 2) ? fxToInteger(the, mxArgv(2)) : 0;
372
205k
  if (z == 0) {
373
102k
    mxResult->kind = XS_NUMBER_KIND;
374
102k
    mxResult->value.number = C_NAN;
375
102k
  }
376
102k
  else {
377
102k
    txS8 r = (x * y) / z;
378
102k
    mxResult->kind = XS_INTEGER_KIND;
379
102k
    mxResult->value.integer = (txInteger)(r & 0x00000000FFFFFFFF);
380
102k
  }
381
205k
}
382
383
void fx_Math_irandom(txMachine* the)
384
133k
{
385
133k
  txInteger min = 0;
386
133k
  txInteger max = 2147483647;
387
133k
  uint32_t result, range, delta;
388
133k
  if (mxArgc > 1) {
389
24.0k
    min = fxToInteger(the, mxArgv(0));
390
24.0k
    max = fxToInteger(the, mxArgv(1));
391
24.0k
  }
392
109k
  else if (mxArgc > 0)
393
89.0k
    max = fxToInteger(the, mxArgv(0));
394
133k
  do  {
395
133k
    result = c_rand();
396
133k
  } while (result == C_RAND_MAX);
397
133k
  if (max >= min) {
398
122k
    range = (uint32_t)max - (uint32_t)min;
399
122k
    delta = (uint32_t)(((uint64_t)result * (uint64_t)range) / (uint64_t)C_RAND_MAX);
400
122k
    mxResult->value.integer = (txInteger)((uint32_t)min + delta);
401
122k
  }
402
11.0k
  else {
403
11.0k
    range = (uint32_t)min - (uint32_t)max;
404
11.0k
    delta = (uint32_t)(((uint64_t)result * (uint64_t)range) / (uint64_t)C_RAND_MAX);
405
11.0k
    mxResult->value.integer = (txInteger)((uint32_t)min - delta);
406
11.0k
  }
407
133k
  mxResult->kind = XS_INTEGER_KIND;
408
133k
}
409
410
void fx_Math_irandom_secure(txMachine* the)
411
0
{
412
0
  mxTypeError("secure mode");
413
0
}
414
415
void fx_Math_irem(txMachine* the)
416
0
{
417
0
  txInteger x = (mxArgc > 0) ? fxToInteger(the, mxArgv(0)) : 0;
418
0
  txInteger y = (mxArgc > 1) ? fxToInteger(the, mxArgv(1)) : 0;
419
0
  if (y == 0) {
420
0
    mxResult->kind = XS_NUMBER_KIND;
421
0
    mxResult->value.number = C_NAN;
422
0
  }
423
0
  else {
424
0
    mxResult->kind = XS_INTEGER_KIND;
425
0
#if mxIntegerDivideOverflowException
426
0
    if ((x == (txInteger)0x80000000) && (y == -1))
427
0
      mxResult->value.integer = 0;
428
0
    else
429
0
#endif
430
0
      mxResult->value.integer = x % y;
431
0
  }
432
0
}
433
434
void fx_Math_log(txMachine* the)
435
24
{
436
24
  mxNanResultIfNoArg;
437
23
  fxToNumber(the, mxArgv(0));
438
23
  mxResult->kind = XS_NUMBER_KIND;
439
23
  mxResult->value.number = c_log(mxArgv(0)->value.number);
440
23
}
441
442
void fx_Math_log1p(txMachine* the)
443
1.33k
{
444
1.33k
  mxNanResultIfNoArg;
445
1.33k
  fxToNumber(the, mxArgv(0));
446
1.33k
  mxResult->kind = XS_NUMBER_KIND;
447
1.33k
  mxResult->value.number = c_log1p(mxArgv(0)->value.number);
448
1.33k
}
449
450
void fx_Math_log10(txMachine* the)
451
224
{
452
224
  mxNanResultIfNoArg;
453
160
  fxToNumber(the, mxArgv(0));
454
160
  mxResult->kind = XS_NUMBER_KIND;
455
160
  mxResult->value.number = c_log10(mxArgv(0)->value.number);
456
160
}
457
458
void fx_Math_log2(txMachine* the)
459
13
{
460
13
  mxNanResultIfNoArg;
461
13
  fxToNumber(the, mxArgv(0));
462
13
  mxResult->kind = XS_NUMBER_KIND;
463
#if mxAndroid
464
  mxResult->value.number = c_log(mxArgv(0)->value.number) / c_log(2);
465
#else
466
13
  mxResult->value.number = c_log2(mxArgv(0)->value.number);
467
13
#endif
468
13
}
469
470
void fx_Math_max(txMachine* the)
471
1.80k
{
472
1.80k
  txInteger c = mxArgc, i = 0;
473
1.80k
  mxResult->kind = XS_NUMBER_KIND;
474
1.80k
  mxResult->value.number = -((txNumber)C_INFINITY);
475
1.80k
  if (0 == c)
476
200
    return;
477
478
1.60k
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
479
1.10k
    mxResult->kind = XS_INTEGER_KIND;
480
1.10k
    mxResult->value.integer = mxArgv(0)->value.integer;
481
1.10k
    i = 1;
482
1.10k
  }
483
484
3.42k
  for (; i < c; i++) {
485
2.28k
    txSlot *slot = mxArgv(i);
486
2.28k
    if (XS_INTEGER_KIND == mxResult->kind) {
487
1.26k
      if (XS_INTEGER_KIND == slot->kind) {
488
885
        if (mxResult->value.integer < slot->value.integer) {
489
562
          mxResult->value.integer = slot->value.integer;
490
562
        }
491
885
        continue;
492
885
      }
493
383
      mxResult->kind = XS_NUMBER_KIND;
494
383
      mxResult->value.number = mxResult->value.integer;
495
383
    }
496
497
1.39k
    txNumber n = fxToNumber(the, slot);
498
1.39k
    if (c_isnan(n)) {
499
8.06k
      for (; i < c; i++)
500
7.60k
        fxToNumber(the, mxArgv(i));
501
456
      mxResult->value.number = C_NAN;
502
456
      return;
503
456
    }
504
940
    if (mxResult->value.number < n)
505
381
      mxResult->value.number = n;
506
559
    else if ((mxResult->value.number == 0) && (n == 0)) {
507
291
      if (c_signbit(mxResult->value.number) != c_signbit(n))
508
63
        mxResult->value.number = 0;
509
291
    }
510
940
  }
511
1.60k
}
512
513
void fx_Math_min(txMachine* the)
514
2.37k
{
515
2.37k
  txInteger c = mxArgc, i = 0;
516
2.37k
  mxResult->kind = XS_NUMBER_KIND;
517
2.37k
  mxResult->value.number = (txNumber)C_INFINITY;
518
2.37k
  if (0 == c)
519
595
    return;
520
521
1.77k
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
522
548
    mxResult->kind = XS_INTEGER_KIND;
523
548
    mxResult->value.integer = mxArgv(0)->value.integer;
524
548
    i = 1;
525
548
  }
526
527
5.63k
  for (; i < c; i++) {
528
5.32k
    txSlot *slot = mxArgv(i);
529
5.32k
    if (XS_INTEGER_KIND == mxResult->kind) {
530
892
      if (XS_INTEGER_KIND == slot->kind) {
531
445
        if (mxResult->value.integer > slot->value.integer)
532
222
          mxResult->value.integer = slot->value.integer;
533
445
        continue;
534
445
      }
535
447
      mxResult->kind = XS_NUMBER_KIND;
536
447
      mxResult->value.number = mxResult->value.integer;
537
447
    }
538
  
539
4.88k
    txNumber n = fxToNumber(the, slot);
540
4.88k
    if (c_isnan(n)) {
541
3.25k
      for (; i < c; i++)
542
1.78k
        fxToNumber(the, mxArgv(i));
543
1.47k
      mxResult->value.number = C_NAN;
544
1.47k
      return;
545
1.47k
    }
546
3.41k
    if (mxResult->value.number > n)
547
1.49k
      mxResult->value.number = n;
548
1.91k
    else if ((mxResult->value.number == 0) && (n == 0)) {
549
961
      if (c_signbit(mxResult->value.number) != c_signbit(n))
550
225
        mxResult->value.number = -0.0;
551
961
    }
552
3.41k
  }
553
1.77k
}
554
555
void fx_Math_mod(txMachine* the)
556
0
{
557
0
  txNumber x = (mxArgc > 0) ? fxToNumber(the, mxArgv(0)) : 0;
558
0
  txNumber y = (mxArgc > 1) ? fxToNumber(the, mxArgv(1)) : 0;
559
0
  mxResult->kind = XS_NUMBER_KIND;
560
0
  mxResult->value.number = c_fmod((c_fmod(x, y) + y), y);
561
0
}
562
563
txNumber fx_pow(txNumber x, txNumber y)
564
2.40M
{
565
2.40M
  if (!c_isfinite(y) && (c_fabs(x) == 1.0))
566
99.0k
    return C_NAN;
567
2.30M
  return c_pow(x, y);
568
2.40M
}
569
570
void fx_Math_pow(txMachine* the)
571
267k
{
572
267k
  txNumber x, y;
573
267k
  mxNanResultIfNoArg;
574
267k
  x = fxToNumber(the, mxArgv(0));
575
267k
  mxNanResultIfNoArg2;
576
210k
  y = fxToNumber(the, mxArgv(1));
577
210k
  mxResult->kind = XS_NUMBER_KIND;
578
210k
  mxResult->value.number = fx_pow(x, y);
579
210k
}
580
581
void fx_Math_random(txMachine* the)
582
106
{
583
106
  uint32_t result;
584
106
  do {
585
106
    result = c_rand();
586
106
  } while (result == C_RAND_MAX);
587
106
  mxResult->kind = XS_NUMBER_KIND;
588
106
  mxResult->value.number = (double)result / (double)C_RAND_MAX;
589
106
}
590
591
void fx_Math_random_secure(txMachine* the)
592
0
{
593
0
  mxTypeError("secure mode");
594
0
}
595
596
void fx_Math_round(txMachine* the)
597
218k
{
598
218k
  txNumber arg;
599
218k
  mxNanResultIfNoArg;
600
218k
  if (XS_INTEGER_KIND == mxArgv(0)->kind) {
601
107k
    mxResult->kind = XS_INTEGER_KIND;
602
107k
    mxResult->value.integer = mxArgv(0)->value.integer;
603
107k
    return;
604
107k
  }
605
110k
  arg = fxToNumber(the, mxArgv(0));
606
110k
  if (c_isfinite(arg) && (-4503599627370495 < arg) && (arg < 4503599627370495)) { // 2 ** 52 - 1
607
109k
    if ((arg < -0.5) || (0.5 <= arg))
608
109k
      arg = c_floor(arg + 0.5);
609
137
    else if (arg < 0)
610
4
      arg = -0.0;
611
133
    else if (arg > 0)
612
11
      arg = 0.0;
613
109k
    }
614
110k
  mxResult->kind = XS_NUMBER_KIND;
615
110k
  mxResult->value.number = arg;
616
110k
  fx_Math_toInteger(the);
617
110k
}
618
619
void fx_Math_sqrt(txMachine* the)
620
1.41k
{
621
1.41k
  mxNanResultIfNoArg;
622
1.41k
  fxToNumber(the, mxArgv(0));
623
1.41k
  mxResult->kind = XS_NUMBER_KIND;
624
1.41k
  mxResult->value.number = c_sqrt(mxArgv(0)->value.number);
625
1.41k
}
626
627
void fx_Math_sumPrecise(txMachine* the)
628
24.8k
{
629
24.8k
  txSlot *iterable, *iterator, *next, *value;
630
24.8k
  xsum_small_accumulator accumulator;
631
24.8k
  txInteger count = 0;
632
24.8k
  txBoolean flag = 1;
633
24.8k
  if (mxArgc < 1)
634
1
    mxTypeError("no items");
635
24.8k
  iterable = mxArgv(0);
636
24.8k
  fxToInstance(the, iterable);
637
24.8k
  mxTemporary(iterator);
638
24.8k
  mxTemporary(next);
639
24.8k
  fxGetIterator(the, iterable, iterator, next, 0);  
640
24.8k
  xsum_small_init(&accumulator);
641
24.8k
  mxTemporary(value);
642
80.9k
  while (fxIteratorNext(the, iterator, next, value)) {
643
56.1k
    mxTry(the) {
644
56.1k
      if (value->kind == XS_INTEGER_KIND) {
645
14.0k
        flag = 0;
646
14.0k
        xsum_small_add1(&accumulator, value->value.integer);
647
14.0k
      }
648
42.0k
      else if (value->kind == XS_NUMBER_KIND) {
649
42.0k
        if (value->value.number != -0.0) {
650
41.3k
          flag = 0;
651
41.3k
          xsum_small_add1(&accumulator, value->value.number);
652
41.3k
        }
653
42.0k
      }
654
12
      else
655
12
        mxTypeError("items[%d]: not a number", count);
656
56.1k
      count++;
657
56.1k
    }
658
56.1k
    mxCatch(the) {
659
12
      fxIteratorReturn(the, iterator, 1);
660
12
      fxJump(the);
661
12
    }
662
56.1k
  }
663
24.7k
  if (flag)
664
222
    mxResult->value.number = -0.0;
665
24.5k
  else
666
24.5k
    mxResult->value.number = xsum_small_round(&accumulator);
667
24.7k
  mxResult->kind = XS_NUMBER_KIND;
668
24.7k
}
669
670
void fx_Math_sign(txMachine* the)
671
9.30k
{
672
9.30k
  txNumber arg;
673
9.30k
  mxNanResultIfNoArg;
674
8.44k
  arg = fxToNumber(the, mxArgv(0));
675
8.44k
  mxResult->kind = XS_NUMBER_KIND;
676
8.44k
  if (c_isnan(arg))
677
5.77k
    mxResult->value.number = C_NAN;
678
2.67k
  else if (arg < 0)
679
463
    mxResult->value.number = -1;
680
2.20k
  else if (arg > 0)
681
760
    mxResult->value.number = 1;
682
1.44k
  else
683
1.44k
    mxResult->value.number = arg;
684
8.44k
  fx_Math_toInteger(the);
685
8.44k
}
686
687
void fx_Math_sin(txMachine* the)
688
11.5k
{
689
11.5k
  mxNanResultIfNoArg;
690
10.4k
  fxToNumber(the, mxArgv(0));
691
10.4k
  mxResult->kind = XS_NUMBER_KIND;
692
10.4k
  mxResult->value.number = c_sin(mxArgv(0)->value.number);
693
10.4k
}
694
695
void fx_Math_sinh(txMachine* the)
696
84.1k
{
697
84.1k
  mxNanResultIfNoArg;
698
82.8k
  fxToNumber(the, mxArgv(0));
699
82.8k
  mxResult->kind = XS_NUMBER_KIND;
700
82.8k
  mxResult->value.number = c_sinh(mxArgv(0)->value.number);
701
82.8k
}
702
703
void fx_Math_tan(txMachine* the)
704
77.9k
{
705
77.9k
  mxNanResultIfNoArg;
706
76.2k
  fxToNumber(the, mxArgv(0));
707
76.2k
  mxResult->kind = XS_NUMBER_KIND;
708
76.2k
  mxResult->value.number = c_tan(mxArgv(0)->value.number);
709
76.2k
}
710
711
void fx_Math_tanh(txMachine* the)
712
5.81k
{
713
5.81k
  mxNanResultIfNoArg;
714
5.61k
  fxToNumber(the, mxArgv(0));
715
5.61k
  mxResult->kind = XS_NUMBER_KIND;
716
5.61k
  mxResult->value.number = c_tanh(mxArgv(0)->value.number);
717
5.61k
}
718
719
void fx_Math_trunc(txMachine* the)
720
114
{
721
114
  mxNanResultIfNoArg;
722
113
  fxToNumber(the, mxArgv(0));
723
113
  mxResult->kind = XS_NUMBER_KIND;
724
113
  mxResult->value.number = c_trunc(mxArgv(0)->value.number);
725
113
  fx_Math_toInteger(the);
726
113
}
727
728
void fx_Math_toInteger(txMachine* the)
729
699k
{
730
699k
  txNumber number = mxResult->value.number;
731
699k
  txInteger integer = (txInteger)number;
732
699k
  txNumber check = integer;
733
699k
  if ((number == check) && (number || !c_signbit(number))) {
734
420k
    mxResult->value.integer = integer;
735
420k
    mxResult->kind = XS_INTEGER_KIND;
736
420k
  }
737
699k
}