Coverage Report

Created: 2026-09-01 07:05

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