MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add math and BigInt

+1055 -6
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.0.7.23') 77 + version_conf.set('ANT_VERSION', '0.0.7.24') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+693 -5
src/ant.c
··· 230 230 }; 231 231 232 232 enum { 233 - TOK_ERR, TOK_EOF, TOK_IDENTIFIER, TOK_NUMBER, TOK_STRING, TOK_SEMICOLON, 233 + TOK_ERR, TOK_EOF, TOK_IDENTIFIER, TOK_NUMBER, TOK_STRING, TOK_SEMICOLON, TOK_BIGINT, 234 234 TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE, TOK_LBRACKET, TOK_RBRACKET, 235 235 TOK_ASYNC = 50, TOK_AWAIT, TOK_BREAK, TOK_CASE, TOK_CATCH, TOK_CLASS, TOK_CONST, TOK_CONTINUE, 236 236 TOK_DEFAULT, TOK_DELETE, TOK_DO, TOK_ELSE, TOK_EXPORT, TOK_FINALLY, TOK_FOR, TOK_FROM, TOK_FUNC, ··· 250 250 251 251 enum { 252 252 T_OBJ, T_PROP, T_STR, T_UNDEF, T_NULL, T_NUM, 253 - T_BOOL, T_FUNC, T_CODEREF, T_CFUNC, T_ERR, T_ARR, T_PROMISE, T_GENERATOR 253 + T_BOOL, T_FUNC, T_CODEREF, T_CFUNC, T_ERR, T_ARR, T_PROMISE, T_GENERATOR, T_BIGINT 254 254 }; 255 255 256 256 static const char *typestr(uint8_t t) { 257 257 const char *names[] = { 258 258 "object", "prop", "string", "undefined", "null", "number", 259 - "boolean", "function", "coderef", "cfunc", "err", "array", "promise", "generator" 259 + "boolean", "function", "coderef", "cfunc", "err", "array", "promise", "generator", "bigint" 260 260 }; 261 261 262 262 return (t < sizeof(names) / sizeof(names[0])) ? names[t] : "??"; ··· 380 380 static jsval_t set_size(struct js *js, jsval_t *args, int nargs); 381 381 static jsval_t set_values(struct js *js, jsval_t *args, int nargs); 382 382 static jsval_t set_forEach(struct js *js, jsval_t *args, int nargs); 383 + 384 + static jsval_t builtin_Math_abs(struct js *js, jsval_t *args, int nargs); 385 + static jsval_t builtin_Math_acos(struct js *js, jsval_t *args, int nargs); 386 + static jsval_t builtin_Math_acosh(struct js *js, jsval_t *args, int nargs); 387 + static jsval_t builtin_Math_asin(struct js *js, jsval_t *args, int nargs); 388 + static jsval_t builtin_Math_asinh(struct js *js, jsval_t *args, int nargs); 389 + static jsval_t builtin_Math_atan(struct js *js, jsval_t *args, int nargs); 390 + static jsval_t builtin_Math_atanh(struct js *js, jsval_t *args, int nargs); 391 + static jsval_t builtin_Math_atan2(struct js *js, jsval_t *args, int nargs); 392 + static jsval_t builtin_Math_cbrt(struct js *js, jsval_t *args, int nargs); 393 + static jsval_t builtin_Math_ceil(struct js *js, jsval_t *args, int nargs); 394 + static jsval_t builtin_Math_clz32(struct js *js, jsval_t *args, int nargs); 395 + static jsval_t builtin_Math_cos(struct js *js, jsval_t *args, int nargs); 396 + static jsval_t builtin_Math_cosh(struct js *js, jsval_t *args, int nargs); 397 + static jsval_t builtin_Math_exp(struct js *js, jsval_t *args, int nargs); 398 + static jsval_t builtin_Math_expm1(struct js *js, jsval_t *args, int nargs); 399 + static jsval_t builtin_Math_floor(struct js *js, jsval_t *args, int nargs); 400 + static jsval_t builtin_Math_fround(struct js *js, jsval_t *args, int nargs); 401 + static jsval_t builtin_Math_hypot(struct js *js, jsval_t *args, int nargs); 402 + static jsval_t builtin_Math_imul(struct js *js, jsval_t *args, int nargs); 403 + static jsval_t builtin_Math_log(struct js *js, jsval_t *args, int nargs); 404 + static jsval_t builtin_Math_log1p(struct js *js, jsval_t *args, int nargs); 405 + static jsval_t builtin_Math_log10(struct js *js, jsval_t *args, int nargs); 406 + static jsval_t builtin_Math_log2(struct js *js, jsval_t *args, int nargs); 407 + static jsval_t builtin_Math_max(struct js *js, jsval_t *args, int nargs); 408 + static jsval_t builtin_Math_min(struct js *js, jsval_t *args, int nargs); 409 + static jsval_t builtin_Math_pow(struct js *js, jsval_t *args, int nargs); 410 + static jsval_t builtin_Math_random(struct js *js, jsval_t *args, int nargs); 411 + static jsval_t builtin_Math_round(struct js *js, jsval_t *args, int nargs); 412 + static jsval_t builtin_Math_sign(struct js *js, jsval_t *args, int nargs); 413 + static jsval_t builtin_Math_sin(struct js *js, jsval_t *args, int nargs); 414 + static jsval_t builtin_Math_sinh(struct js *js, jsval_t *args, int nargs); 415 + static jsval_t builtin_Math_sqrt(struct js *js, jsval_t *args, int nargs); 416 + static jsval_t builtin_Math_tan(struct js *js, jsval_t *args, int nargs); 417 + static jsval_t builtin_Math_tanh(struct js *js, jsval_t *args, int nargs); 418 + static jsval_t builtin_Math_trunc(struct js *js, jsval_t *args, int nargs); 383 419 384 420 static jsval_t call_js(struct js *js, const char *fn, jsoff_t fnlen, jsval_t closure_scope); 385 421 static jsval_t call_js_with_args(struct js *js, jsval_t func, jsval_t *args, int nargs); ··· 706 742 static void pop_stringify(void) { 707 743 if (stringify_depth > 0) stringify_depth--; 708 744 } 745 + 746 + static size_t strbigint(struct js *js, jsval_t value, char *buf, size_t len); 709 747 710 748 static size_t strarr(struct js *js, jsval_t obj, char *buf, size_t len) { 711 749 if (is_circular(obj)) return cpy(buf, len, "[Circular]", 10); ··· 1080 1118 case T_OBJ: return strobj(js, value, buf, len); 1081 1119 case T_STR: return strstring(js, value, buf, len); 1082 1120 case T_NUM: return strnum(value, buf, len); 1121 + case T_BIGINT: return strbigint(js, value, buf, len); 1083 1122 case T_PROMISE: return strpromise(js, value, buf, len); 1084 1123 case T_FUNC: return strfunc(js, value, buf, len); 1085 1124 case T_CFUNC: return (size_t) snprintf(buf, len, "\"c_func_0x%lx\"", (unsigned long) vdata(value)); ··· 1101 1140 return buf; 1102 1141 } 1103 1142 1143 + static bool bigint_is_zero(struct js *js, jsval_t v); 1144 + 1104 1145 bool js_truthy(struct js *js, jsval_t v) { 1105 1146 uint8_t t = vtype(v); 1106 1147 return (t == T_BOOL && vdata(v) != 0) || (t == T_NUM && tod(v) != 0.0) || 1107 - (t == T_OBJ || t == T_FUNC || t == T_ARR) || (t == T_STR && vstrlen(js, v) > 0); 1148 + (t == T_OBJ || t == T_FUNC || t == T_ARR) || (t == T_STR && vstrlen(js, v) > 0) || 1149 + (t == T_BIGINT && !bigint_is_zero(js, v)); 1108 1150 } 1109 1151 1110 1152 static bool js_try_grow_memory(struct js *js, size_t needed) { ··· 1184 1226 return mkentity(js, (jsoff_t) ((n << 2) | T_STR), ptr, n); 1185 1227 } 1186 1228 1229 + static jsval_t mkbigint(struct js *js, const char *digits, size_t len, bool negative) { 1230 + size_t total = len + 2; 1231 + jsoff_t ofs = js_alloc(js, total + sizeof(jsoff_t)); 1232 + if (ofs == (jsoff_t) ~0) return js_mkerr(js, "oom"); 1233 + jsoff_t header = (jsoff_t) (total << 4); 1234 + memcpy(&js->mem[ofs], &header, sizeof(header)); 1235 + js->mem[ofs + sizeof(header)] = negative ? 1 : 0; 1236 + if (digits) memcpy(&js->mem[ofs + sizeof(header) + 1], digits, len); 1237 + js->mem[ofs + sizeof(header) + 1 + len] = 0; 1238 + return mkval(T_BIGINT, ofs); 1239 + } 1240 + 1241 + static bool bigint_IsNegative(struct js *js, jsval_t v) { 1242 + jsoff_t ofs = (jsoff_t) vdata(v); 1243 + return js->mem[ofs + sizeof(jsoff_t)] == 1; 1244 + } 1245 + 1246 + static const char *bigint_digits(struct js *js, jsval_t v, size_t *len) { 1247 + jsoff_t ofs = (jsoff_t) vdata(v); 1248 + jsoff_t header = loadoff(js, ofs); 1249 + size_t total = (header >> 4) - 2; 1250 + if (len) *len = total; 1251 + return (const char *)&js->mem[ofs + sizeof(jsoff_t) + 1]; 1252 + } 1253 + 1254 + static int bigint_cmp_abs(const char *a, size_t alen, const char *b, size_t blen) { 1255 + while (alen > 1 && a[0] == '0') { a++; alen--; } 1256 + while (blen > 1 && b[0] == '0') { b++; blen--; } 1257 + if (alen != blen) return alen > blen ? 1 : -1; 1258 + for (size_t i = 0; i < alen; i++) { 1259 + if (a[i] != b[i]) return a[i] > b[i] ? 1 : -1; 1260 + } 1261 + return 0; 1262 + } 1263 + 1264 + static char *bigint_add_abs(const char *a, size_t alen, const char *b, size_t blen, size_t *rlen) { 1265 + size_t maxlen = (alen > blen ? alen : blen) + 1; 1266 + char *result = (char *)malloc(maxlen + 1); 1267 + if (!result) return NULL; 1268 + int carry = 0; 1269 + size_t ri = 0; 1270 + for (size_t i = 0; i < maxlen; i++) { 1271 + int da = (i < alen) ? (a[alen - 1 - i] - '0') : 0; 1272 + int db = (i < blen) ? (b[blen - 1 - i] - '0') : 0; 1273 + int sum = da + db + carry; 1274 + carry = sum / 10; 1275 + result[ri++] = (char)('0' + (sum % 10)); 1276 + } 1277 + while (ri > 1 && result[ri - 1] == '0') ri--; 1278 + for (size_t i = 0; i < ri / 2; i++) { 1279 + char tmp = result[i]; result[i] = result[ri - 1 - i]; result[ri - 1 - i] = tmp; 1280 + } 1281 + result[ri] = 0; 1282 + *rlen = ri; 1283 + return result; 1284 + } 1285 + 1286 + static char *bigint_sub_abs(const char *a, size_t alen, const char *b, size_t blen, size_t *rlen) { 1287 + char *result = (char *)malloc(alen + 1); 1288 + if (!result) return NULL; 1289 + int borrow = 0; 1290 + size_t ri = 0; 1291 + for (size_t i = 0; i < alen; i++) { 1292 + int da = a[alen - 1 - i] - '0'; 1293 + int db = (i < blen) ? (b[blen - 1 - i] - '0') : 0; 1294 + int diff = da - db - borrow; 1295 + if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } 1296 + result[ri++] = (char)('0' + diff); 1297 + } 1298 + while (ri > 1 && result[ri - 1] == '0') ri--; 1299 + for (size_t i = 0; i < ri / 2; i++) { 1300 + char tmp = result[i]; result[i] = result[ri - 1 - i]; result[ri - 1 - i] = tmp; 1301 + } 1302 + result[ri] = 0; 1303 + *rlen = ri; 1304 + return result; 1305 + } 1306 + 1307 + static char *bigint_mul_abs(const char *a, size_t alen, const char *b, size_t blen, size_t *rlen) { 1308 + size_t reslen = alen + blen; 1309 + int *temp = (int *)calloc(reslen, sizeof(int)); 1310 + if (!temp) return NULL; 1311 + for (size_t i = 0; i < alen; i++) { 1312 + for (size_t j = 0; j < blen; j++) { 1313 + temp[i + j] += (a[alen - 1 - i] - '0') * (b[blen - 1 - j] - '0'); 1314 + } 1315 + } 1316 + for (size_t i = 0; i < reslen - 1; i++) { 1317 + temp[i + 1] += temp[i] / 10; 1318 + temp[i] %= 10; 1319 + } 1320 + size_t start = reslen - 1; 1321 + while (start > 0 && temp[start] == 0) start--; 1322 + char *result = (char *)malloc(start + 2); 1323 + if (!result) { free(temp); return NULL; } 1324 + for (size_t i = 0; i <= start; i++) result[i] = (char)('0' + temp[start - i]); 1325 + result[start + 1] = 0; 1326 + *rlen = start + 1; 1327 + free(temp); 1328 + return result; 1329 + } 1330 + 1331 + static char *bigint_div_abs(const char *a, size_t alen, const char *b, size_t blen, size_t *rlen, char **rem, size_t *remlen) { 1332 + if (blen == 1 && b[0] == '0') return NULL; 1333 + if (bigint_cmp_abs(a, alen, b, blen) < 0) { 1334 + char *result = (char *)malloc(2); result[0] = '0'; result[1] = 0; *rlen = 1; 1335 + if (rem) { *rem = (char *)malloc(alen + 1); memcpy(*rem, a, alen); (*rem)[alen] = 0; *remlen = alen; } 1336 + return result; 1337 + } 1338 + char *current = (char *)calloc(alen + 1, 1); 1339 + char *result = (char *)calloc(alen + 1, 1); 1340 + if (!current || !result) { free(current); free(result); return NULL; } 1341 + size_t curlen = 0, reslen = 0; 1342 + for (size_t i = 0; i < alen; i++) { 1343 + if (curlen == 1 && current[0] == '0') curlen = 0; 1344 + current[curlen++] = a[i]; current[curlen] = 0; 1345 + int count = 0; 1346 + while (bigint_cmp_abs(current, curlen, b, blen) >= 0) { 1347 + size_t sublen; 1348 + char *sub = bigint_sub_abs(current, curlen, b, blen, &sublen); 1349 + if (!sub) break; 1350 + memcpy(current, sub, sublen + 1); curlen = sublen; 1351 + free(sub); count++; 1352 + } 1353 + result[reslen++] = (char)('0' + count); 1354 + } 1355 + size_t start = 0; 1356 + while (start < reslen - 1 && result[start] == '0') start++; 1357 + memmove(result, result + start, reslen - start + 1); 1358 + *rlen = reslen - start; 1359 + if (rem) { *rem = current; *remlen = curlen; } else free(current); 1360 + return result; 1361 + } 1362 + 1363 + static jsval_t bigint_add(struct js *js, jsval_t a, jsval_t b) { 1364 + bool aneg = bigint_IsNegative(js, a), bneg = bigint_IsNegative(js, b); 1365 + size_t alen, blen; 1366 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1367 + char *result; size_t rlen; bool rneg; 1368 + if (aneg == bneg) { 1369 + result = bigint_add_abs(ad, alen, bd, blen, &rlen); rneg = aneg; 1370 + } else { 1371 + int cmp = bigint_cmp_abs(ad, alen, bd, blen); 1372 + if (cmp >= 0) { result = bigint_sub_abs(ad, alen, bd, blen, &rlen); rneg = aneg; } 1373 + else { result = bigint_sub_abs(bd, blen, ad, alen, &rlen); rneg = bneg; } 1374 + } 1375 + if (!result) return js_mkerr(js, "oom"); 1376 + if (rlen == 1 && result[0] == '0') rneg = false; 1377 + jsval_t r = mkbigint(js, result, rlen, rneg); 1378 + free(result); 1379 + return r; 1380 + } 1381 + 1382 + static jsval_t bigint_sub(struct js *js, jsval_t a, jsval_t b) { 1383 + bool aneg = bigint_IsNegative(js, a), bneg = bigint_IsNegative(js, b); 1384 + size_t alen, blen; 1385 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1386 + char *result; size_t rlen; bool rneg; 1387 + if (aneg != bneg) { 1388 + result = bigint_add_abs(ad, alen, bd, blen, &rlen); rneg = aneg; 1389 + } else { 1390 + int cmp = bigint_cmp_abs(ad, alen, bd, blen); 1391 + if (cmp >= 0) { result = bigint_sub_abs(ad, alen, bd, blen, &rlen); rneg = aneg; } 1392 + else { result = bigint_sub_abs(bd, blen, ad, alen, &rlen); rneg = !aneg; } 1393 + } 1394 + if (!result) return js_mkerr(js, "oom"); 1395 + if (rlen == 1 && result[0] == '0') rneg = false; 1396 + jsval_t r = mkbigint(js, result, rlen, rneg); 1397 + free(result); 1398 + return r; 1399 + } 1400 + 1401 + static jsval_t bigint_mul(struct js *js, jsval_t a, jsval_t b) { 1402 + bool aneg = bigint_IsNegative(js, a), bneg = bigint_IsNegative(js, b); 1403 + size_t alen, blen; 1404 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1405 + size_t rlen; 1406 + char *result = bigint_mul_abs(ad, alen, bd, blen, &rlen); 1407 + if (!result) return js_mkerr(js, "oom"); 1408 + bool rneg = (aneg != bneg) && !(rlen == 1 && result[0] == '0'); 1409 + jsval_t r = mkbigint(js, result, rlen, rneg); 1410 + free(result); 1411 + return r; 1412 + } 1413 + 1414 + static jsval_t bigint_div(struct js *js, jsval_t a, jsval_t b) { 1415 + bool aneg = bigint_IsNegative(js, a), bneg = bigint_IsNegative(js, b); 1416 + size_t alen, blen; 1417 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1418 + if (blen == 1 && bd[0] == '0') return js_mkerr(js, "Division by zero"); 1419 + size_t rlen; 1420 + char *result = bigint_div_abs(ad, alen, bd, blen, &rlen, NULL, NULL); 1421 + if (!result) return js_mkerr(js, "oom"); 1422 + bool rneg = (aneg != bneg) && !(rlen == 1 && result[0] == '0'); 1423 + jsval_t r = mkbigint(js, result, rlen, rneg); 1424 + free(result); 1425 + return r; 1426 + } 1427 + 1428 + static jsval_t bigint_mod(struct js *js, jsval_t a, jsval_t b) { 1429 + bool aneg = bigint_IsNegative(js, a); 1430 + size_t alen, blen; 1431 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1432 + if (blen == 1 && bd[0] == '0') return js_mkerr(js, "Division by zero"); 1433 + size_t rlen, remlen; char *rem; 1434 + char *result = bigint_div_abs(ad, alen, bd, blen, &rlen, &rem, &remlen); 1435 + if (!result) return js_mkerr(js, "oom"); 1436 + free(result); 1437 + bool rneg = aneg && !(remlen == 1 && rem[0] == '0'); 1438 + jsval_t r = mkbigint(js, rem, remlen, rneg); 1439 + free(rem); 1440 + return r; 1441 + } 1442 + 1443 + static jsval_t bigint_neg(struct js *js, jsval_t a) { 1444 + size_t len; 1445 + const char *digits = bigint_digits(js, a, &len); 1446 + bool neg = bigint_IsNegative(js, a); 1447 + if (len == 1 && digits[0] == '0') return mkbigint(js, digits, len, false); 1448 + return mkbigint(js, digits, len, !neg); 1449 + } 1450 + 1451 + static int bigint_compare(struct js *js, jsval_t a, jsval_t b) { 1452 + bool aneg = bigint_IsNegative(js, a), bneg = bigint_IsNegative(js, b); 1453 + size_t alen, blen; 1454 + const char *ad = bigint_digits(js, a, &alen), *bd = bigint_digits(js, b, &blen); 1455 + if (aneg && !bneg) return -1; 1456 + if (!aneg && bneg) return 1; 1457 + int cmp = bigint_cmp_abs(ad, alen, bd, blen); 1458 + return aneg ? -cmp : cmp; 1459 + } 1460 + 1461 + static bool bigint_is_zero(struct js *js, jsval_t v) { 1462 + size_t len; 1463 + const char *digits = bigint_digits(js, v, &len); 1464 + return len == 1 && digits[0] == '0'; 1465 + } 1466 + 1467 + static size_t strbigint(struct js *js, jsval_t value, char *buf, size_t len) { 1468 + bool neg = bigint_IsNegative(js, value); 1469 + size_t dlen; 1470 + const char *digits = bigint_digits(js, value, &dlen); 1471 + size_t n = 0; 1472 + if (neg) n += cpy(buf + n, len - n, "-", 1); 1473 + n += cpy(buf + n, len - n, digits, dlen); 1474 + return n; 1475 + } 1476 + 1477 + static jsval_t builtin_BigInt(struct js *js, jsval_t *args, int nargs) { 1478 + if (nargs < 1) return mkbigint(js, "0", 1, false); 1479 + jsval_t arg = args[0]; 1480 + if (vtype(arg) == T_BIGINT) return arg; 1481 + if (vtype(arg) == T_NUM) { 1482 + double d = tod(arg); 1483 + if (!isfinite(d)) return js_mkerr(js, "Cannot convert Infinity or NaN to BigInt"); 1484 + if (d != trunc(d)) return js_mkerr(js, "Cannot convert non-integer to BigInt"); 1485 + bool neg = d < 0; 1486 + if (neg) d = -d; 1487 + char buf[64]; 1488 + snprintf(buf, sizeof(buf), "%.0f", d); 1489 + return mkbigint(js, buf, strlen(buf), neg); 1490 + } 1491 + if (vtype(arg) == T_STR) { 1492 + jsoff_t slen, off = vstr(js, arg, &slen); 1493 + const char *str = (const char *)&js->mem[off]; 1494 + bool neg = false; 1495 + size_t i = 0; 1496 + if (slen > 0 && str[0] == '-') { neg = true; i++; } 1497 + else if (slen > 0 && str[0] == '+') { i++; } 1498 + while (i < slen && str[i] == '0') i++; 1499 + if (i >= slen) return mkbigint(js, "0", 1, false); 1500 + for (size_t j = i; j < slen; j++) { 1501 + if (!is_digit(str[j])) return js_mkerr(js, "Cannot convert string to BigInt"); 1502 + } 1503 + return mkbigint(js, str + i, slen - i, neg); 1504 + } 1505 + if (vtype(arg) == T_BOOL) { 1506 + return mkbigint(js, vdata(arg) ? "1" : "0", 1, false); 1507 + } 1508 + return js_mkerr(js, "Cannot convert to BigInt"); 1509 + } 1510 + 1511 + static jsval_t builtin_BigInt_asIntN(struct js *js, jsval_t *args, int nargs) { 1512 + (void)js; (void)args; (void)nargs; 1513 + return js_mkerr(js, "BigInt.asIntN not implemented"); 1514 + } 1515 + 1516 + static jsval_t builtin_BigInt_asUintN(struct js *js, jsval_t *args, int nargs) { 1517 + (void)js; (void)args; (void)nargs; 1518 + return js_mkerr(js, "BigInt.asUintN not implemented"); 1519 + } 1520 + 1187 1521 static jsval_t mkobj(struct js *js, jsoff_t parent) { 1188 1522 return mkentity(js, 0 | T_OBJ, &parent, sizeof(parent)); 1189 1523 } ··· 1791 2125 } 1792 2126 char *end; 1793 2127 js->tval = tov(strtod(buf, &end)); 1794 - TOK(TOK_NUMBER, (jsoff_t) (end - buf)); 2128 + jsoff_t numlen = (jsoff_t) (end - buf); 2129 + if (js->toff + numlen < js->clen && buf[numlen] == 'n') { 2130 + js->tok = TOK_BIGINT; 2131 + js->tlen = numlen + 1; 2132 + } else { 2133 + TOK(TOK_NUMBER, numlen); 2134 + } 2135 + break; 1795 2136 } 1796 2137 default: js->tok = parseident(buf, js->clen - js->toff, &js->tlen); break; 1797 2138 } ··· 2811 3152 do_assign_op(js, TOK_MINUS_ASSIGN, lhs, tov(1)); return l; 2812 3153 } 2813 3154 case TOK_NOT: return mkval(T_BOOL, !js_truthy(js, r)); 3155 + case TOK_UMINUS: 3156 + if (vtype(r) == T_BIGINT) return bigint_neg(js, r); 3157 + break; 3158 + case TOK_UPLUS: 3159 + if (vtype(r) == T_BIGINT) return js_mkerr(js, "Cannot convert BigInt to number"); 3160 + break; 2814 3161 } 2815 3162 if (is_assign(op)) return do_assign_op(js, op, lhs, r); 2816 3163 if (op == TOK_EQ || op == TOK_NE) { ··· 2824 3171 eq = tod(l) == tod(r); 2825 3172 } else if (vtype(l) == T_BOOL) { 2826 3173 eq = vdata(l) == vdata(r); 3174 + } else if (vtype(l) == T_BIGINT) { 3175 + eq = bigint_compare(js, l, r) == 0; 2827 3176 } else { 2828 3177 eq = vdata(l) == vdata(r); 2829 3178 } 2830 3179 } 2831 3180 return mkval(T_BOOL, op == TOK_EQ ? eq : !eq); 3181 + } 3182 + if (vtype(l) == T_BIGINT || vtype(r) == T_BIGINT) { 3183 + if (vtype(l) != T_BIGINT || vtype(r) != T_BIGINT) { 3184 + return js_mkerr(js, "Cannot mix BigInt and other types"); 3185 + } 3186 + switch (op) { 3187 + case TOK_PLUS: return bigint_add(js, l, r); 3188 + case TOK_MINUS: return bigint_sub(js, l, r); 3189 + case TOK_MUL: return bigint_mul(js, l, r); 3190 + case TOK_DIV: return bigint_div(js, l, r); 3191 + case TOK_REM: return bigint_mod(js, l, r); 3192 + case TOK_LT: return mkval(T_BOOL, bigint_compare(js, l, r) < 0); 3193 + case TOK_GT: return mkval(T_BOOL, bigint_compare(js, l, r) > 0); 3194 + case TOK_LE: return mkval(T_BOOL, bigint_compare(js, l, r) <= 0); 3195 + case TOK_GE: return mkval(T_BOOL, bigint_compare(js, l, r) >= 0); 3196 + default: return js_mkerr(js, "unsupported BigInt operation"); 3197 + } 2832 3198 } 2833 3199 if (op == TOK_PLUS && (vtype(l) == T_STR || vtype(r) == T_STR || vtype(l) == T_ARR || vtype(r) == T_ARR)) { 2834 3200 jsval_t l_str = l, r_str = r; ··· 3184 3550 return js_mkstr(js, NULL, n1); 3185 3551 } 3186 3552 3553 + static jsval_t js_bigint_literal(struct js *js) { 3554 + const char *start = &js->code[js->toff]; 3555 + size_t len = js->tlen - 1; 3556 + while (len > 1 && start[0] == '0') { start++; len--; } 3557 + bool neg = false; 3558 + if (len > 0 && start[0] == '-') { neg = true; start++; len--; } 3559 + return mkbigint(js, start, len, neg); 3560 + } 3561 + 3187 3562 static jsval_t js_arr_literal(struct js *js) { 3188 3563 uint8_t exe = !(js->flags & F_NOEXEC); 3189 3564 jsval_t arr = exe ? mkarr(js) : js_mkundef(); ··· 3449 3824 } 3450 3825 return js_mkerr(js, "parse error"); 3451 3826 case TOK_NUMBER: return js->tval; 3827 + case TOK_BIGINT: return js_bigint_literal(js); 3452 3828 case TOK_STRING: return js_str_literal(js); 3453 3829 case TOK_TEMPLATE: return js_template_literal(js); 3454 3830 case TOK_LBRACE: return js_obj_literal(js); ··· 6131 6507 return tov(timestamp_ms); 6132 6508 } 6133 6509 6510 + static jsval_t builtin_Math_abs(struct js *js, jsval_t *args, int nargs) { 6511 + (void) js; 6512 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6513 + return tov(fabs(tod(args[0]))); 6514 + } 6515 + 6516 + static jsval_t builtin_Math_acos(struct js *js, jsval_t *args, int nargs) { 6517 + (void) js; 6518 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6519 + return tov(acos(tod(args[0]))); 6520 + } 6521 + 6522 + static jsval_t builtin_Math_acosh(struct js *js, jsval_t *args, int nargs) { 6523 + (void) js; 6524 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6525 + return tov(acosh(tod(args[0]))); 6526 + } 6527 + 6528 + static jsval_t builtin_Math_asin(struct js *js, jsval_t *args, int nargs) { 6529 + (void) js; 6530 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6531 + return tov(asin(tod(args[0]))); 6532 + } 6533 + 6534 + static jsval_t builtin_Math_asinh(struct js *js, jsval_t *args, int nargs) { 6535 + (void) js; 6536 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6537 + return tov(asinh(tod(args[0]))); 6538 + } 6539 + 6540 + static jsval_t builtin_Math_atan(struct js *js, jsval_t *args, int nargs) { 6541 + (void) js; 6542 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6543 + return tov(atan(tod(args[0]))); 6544 + } 6545 + 6546 + static jsval_t builtin_Math_atanh(struct js *js, jsval_t *args, int nargs) { 6547 + (void) js; 6548 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6549 + return tov(atanh(tod(args[0]))); 6550 + } 6551 + 6552 + static jsval_t builtin_Math_atan2(struct js *js, jsval_t *args, int nargs) { 6553 + (void) js; 6554 + if (nargs < 2 || vtype(args[0]) != T_NUM || vtype(args[1]) != T_NUM) return tov(NAN); 6555 + return tov(atan2(tod(args[0]), tod(args[1]))); 6556 + } 6557 + 6558 + static jsval_t builtin_Math_cbrt(struct js *js, jsval_t *args, int nargs) { 6559 + (void) js; 6560 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6561 + return tov(cbrt(tod(args[0]))); 6562 + } 6563 + 6564 + static jsval_t builtin_Math_ceil(struct js *js, jsval_t *args, int nargs) { 6565 + (void) js; 6566 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6567 + return tov(ceil(tod(args[0]))); 6568 + } 6569 + 6570 + static jsval_t builtin_Math_clz32(struct js *js, jsval_t *args, int nargs) { 6571 + (void) js; 6572 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(32); 6573 + uint32_t n = (uint32_t) tod(args[0]); 6574 + if (n == 0) return tov(32); 6575 + int count = 0; 6576 + while ((n & 0x80000000U) == 0) { count++; n <<= 1; } 6577 + return tov((double) count); 6578 + } 6579 + 6580 + static jsval_t builtin_Math_cos(struct js *js, jsval_t *args, int nargs) { 6581 + (void) js; 6582 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6583 + return tov(cos(tod(args[0]))); 6584 + } 6585 + 6586 + static jsval_t builtin_Math_cosh(struct js *js, jsval_t *args, int nargs) { 6587 + (void) js; 6588 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6589 + return tov(cosh(tod(args[0]))); 6590 + } 6591 + 6592 + static jsval_t builtin_Math_exp(struct js *js, jsval_t *args, int nargs) { 6593 + (void) js; 6594 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6595 + return tov(exp(tod(args[0]))); 6596 + } 6597 + 6598 + static jsval_t builtin_Math_expm1(struct js *js, jsval_t *args, int nargs) { 6599 + (void) js; 6600 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6601 + return tov(expm1(tod(args[0]))); 6602 + } 6603 + 6604 + static jsval_t builtin_Math_floor(struct js *js, jsval_t *args, int nargs) { 6605 + (void) js; 6606 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6607 + return tov(floor(tod(args[0]))); 6608 + } 6609 + 6610 + static jsval_t builtin_Math_fround(struct js *js, jsval_t *args, int nargs) { 6611 + (void) js; 6612 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6613 + return tov((double)(float)tod(args[0])); 6614 + } 6615 + 6616 + static jsval_t builtin_Math_hypot(struct js *js, jsval_t *args, int nargs) { 6617 + (void) js; 6618 + if (nargs == 0) return tov(0.0); 6619 + double sum = 0.0; 6620 + for (int i = 0; i < nargs; i++) { 6621 + if (vtype(args[i]) != T_NUM) return tov(NAN); 6622 + double v = tod(args[i]); 6623 + sum += v * v; 6624 + } 6625 + return tov(sqrt(sum)); 6626 + } 6627 + 6628 + static int32_t toInt32(double d) { 6629 + if (isnan(d) || isinf(d) || d == 0) return 0; 6630 + double int_val = trunc(d); 6631 + double two32 = (double)(1ULL << 32); 6632 + double two31 = (double)(1ULL << 31); 6633 + double mod_val = fmod(int_val, two32); 6634 + if (mod_val < 0) mod_val += two32; 6635 + if (mod_val >= two31) mod_val -= two32; 6636 + return (int32_t)mod_val; 6637 + } 6638 + 6639 + static jsval_t builtin_Math_imul(struct js *js, jsval_t *args, int nargs) { 6640 + (void) js; 6641 + if (nargs < 2) return tov(0); 6642 + int32_t a = toInt32(tod(args[0])); 6643 + int32_t b = toInt32(tod(args[1])); 6644 + return tov((double)((int32_t)((uint32_t)a * (uint32_t)b))); 6645 + } 6646 + 6647 + static jsval_t builtin_Math_log(struct js *js, jsval_t *args, int nargs) { 6648 + (void) js; 6649 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6650 + return tov(log(tod(args[0]))); 6651 + } 6652 + 6653 + static jsval_t builtin_Math_log1p(struct js *js, jsval_t *args, int nargs) { 6654 + (void) js; 6655 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6656 + return tov(log1p(tod(args[0]))); 6657 + } 6658 + 6659 + static jsval_t builtin_Math_log10(struct js *js, jsval_t *args, int nargs) { 6660 + (void) js; 6661 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6662 + return tov(log10(tod(args[0]))); 6663 + } 6664 + 6665 + static jsval_t builtin_Math_log2(struct js *js, jsval_t *args, int nargs) { 6666 + (void) js; 6667 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6668 + return tov(log2(tod(args[0]))); 6669 + } 6670 + 6671 + static jsval_t builtin_Math_max(struct js *js, jsval_t *args, int nargs) { 6672 + (void) js; 6673 + if (nargs == 0) return tov(-INFINITY); 6674 + double max_val = -INFINITY; 6675 + for (int i = 0; i < nargs; i++) { 6676 + if (vtype(args[i]) != T_NUM) return tov(NAN); 6677 + double v = tod(args[i]); 6678 + if (isnan(v)) return tov(NAN); 6679 + if (v > max_val) max_val = v; 6680 + } 6681 + return tov(max_val); 6682 + } 6683 + 6684 + static jsval_t builtin_Math_min(struct js *js, jsval_t *args, int nargs) { 6685 + (void) js; 6686 + if (nargs == 0) return tov(INFINITY); 6687 + double min_val = INFINITY; 6688 + for (int i = 0; i < nargs; i++) { 6689 + if (vtype(args[i]) != T_NUM) return tov(NAN); 6690 + double v = tod(args[i]); 6691 + if (isnan(v)) return tov(NAN); 6692 + if (v < min_val) min_val = v; 6693 + } 6694 + return tov(min_val); 6695 + } 6696 + 6697 + static jsval_t builtin_Math_pow(struct js *js, jsval_t *args, int nargs) { 6698 + (void) js; 6699 + if (nargs < 2 || vtype(args[0]) != T_NUM || vtype(args[1]) != T_NUM) return tov(NAN); 6700 + return tov(pow(tod(args[0]), tod(args[1]))); 6701 + } 6702 + 6703 + static bool random_seeded = false; 6704 + 6705 + static jsval_t builtin_Math_random(struct js *js, jsval_t *args, int nargs) { 6706 + (void) js; 6707 + (void) args; 6708 + (void) nargs; 6709 + if (!random_seeded) { 6710 + srand((unsigned int) time(NULL)); 6711 + random_seeded = true; 6712 + } 6713 + return tov((double) rand() / ((double) RAND_MAX + 1.0)); 6714 + } 6715 + 6716 + static jsval_t builtin_Math_round(struct js *js, jsval_t *args, int nargs) { 6717 + (void) js; 6718 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6719 + double x = tod(args[0]); 6720 + if (isnan(x) || isinf(x)) return tov(x); 6721 + return tov(floor(x + 0.5)); 6722 + } 6723 + 6724 + static jsval_t builtin_Math_sign(struct js *js, jsval_t *args, int nargs) { 6725 + (void) js; 6726 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6727 + double v = tod(args[0]); 6728 + if (isnan(v)) return tov(NAN); 6729 + if (v > 0) return tov(1.0); 6730 + if (v < 0) return tov(-1.0); 6731 + return tov(v); 6732 + } 6733 + 6734 + static jsval_t builtin_Math_sin(struct js *js, jsval_t *args, int nargs) { 6735 + (void) js; 6736 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6737 + return tov(sin(tod(args[0]))); 6738 + } 6739 + 6740 + static jsval_t builtin_Math_sinh(struct js *js, jsval_t *args, int nargs) { 6741 + (void) js; 6742 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6743 + return tov(sinh(tod(args[0]))); 6744 + } 6745 + 6746 + static jsval_t builtin_Math_sqrt(struct js *js, jsval_t *args, int nargs) { 6747 + (void) js; 6748 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6749 + return tov(sqrt(tod(args[0]))); 6750 + } 6751 + 6752 + static jsval_t builtin_Math_tan(struct js *js, jsval_t *args, int nargs) { 6753 + (void) js; 6754 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6755 + return tov(tan(tod(args[0]))); 6756 + } 6757 + 6758 + static jsval_t builtin_Math_tanh(struct js *js, jsval_t *args, int nargs) { 6759 + (void) js; 6760 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6761 + return tov(tanh(tod(args[0]))); 6762 + } 6763 + 6764 + static jsval_t builtin_Math_trunc(struct js *js, jsval_t *args, int nargs) { 6765 + (void) js; 6766 + if (nargs < 1 || vtype(args[0]) != T_NUM) return tov(NAN); 6767 + return tov(trunc(tod(args[0]))); 6768 + } 6769 + 6134 6770 static jsval_t builtin_object_keys(struct js *js, jsval_t *args, int nargs) { 6135 6771 if (nargs == 0) return mkarr(js); 6136 6772 jsval_t obj = args[0]; ··· 8863 9499 8864 9500 setprop(js, glob, js_mkstr(js, "NaN", 3), tov(NAN)); 8865 9501 setprop(js, glob, js_mkstr(js, "Infinity", 8), tov(INFINITY)); 9502 + 9503 + jsval_t bigint_ctor_obj = mkobj(js, 0); 9504 + setprop(js, bigint_ctor_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_BigInt)); 9505 + setprop(js, bigint_ctor_obj, js_mkstr(js, "asIntN", 6), js_mkfun(builtin_BigInt_asIntN)); 9506 + setprop(js, bigint_ctor_obj, js_mkstr(js, "asUintN", 7), js_mkfun(builtin_BigInt_asUintN)); 9507 + setprop(js, glob, js_mkstr(js, "BigInt", 6), mkval(T_FUNC, vdata(bigint_ctor_obj))); 9508 + 9509 + jsval_t math_obj = mkobj(js, 0); 9510 + setprop(js, math_obj, js_mkstr(js, "E", 1), tov(M_E)); 9511 + setprop(js, math_obj, js_mkstr(js, "LN10", 4), tov(M_LN10)); 9512 + setprop(js, math_obj, js_mkstr(js, "LN2", 3), tov(M_LN2)); 9513 + setprop(js, math_obj, js_mkstr(js, "LOG10E", 6), tov(M_LOG10E)); 9514 + setprop(js, math_obj, js_mkstr(js, "LOG2E", 5), tov(M_LOG2E)); 9515 + setprop(js, math_obj, js_mkstr(js, "PI", 2), tov(M_PI)); 9516 + setprop(js, math_obj, js_mkstr(js, "SQRT1_2", 7), tov(M_SQRT1_2)); 9517 + setprop(js, math_obj, js_mkstr(js, "SQRT2", 5), tov(M_SQRT2)); 9518 + setprop(js, math_obj, js_mkstr(js, "abs", 3), js_mkfun(builtin_Math_abs)); 9519 + setprop(js, math_obj, js_mkstr(js, "acos", 4), js_mkfun(builtin_Math_acos)); 9520 + setprop(js, math_obj, js_mkstr(js, "acosh", 5), js_mkfun(builtin_Math_acosh)); 9521 + setprop(js, math_obj, js_mkstr(js, "asin", 4), js_mkfun(builtin_Math_asin)); 9522 + setprop(js, math_obj, js_mkstr(js, "asinh", 5), js_mkfun(builtin_Math_asinh)); 9523 + setprop(js, math_obj, js_mkstr(js, "atan", 4), js_mkfun(builtin_Math_atan)); 9524 + setprop(js, math_obj, js_mkstr(js, "atanh", 5), js_mkfun(builtin_Math_atanh)); 9525 + setprop(js, math_obj, js_mkstr(js, "atan2", 5), js_mkfun(builtin_Math_atan2)); 9526 + setprop(js, math_obj, js_mkstr(js, "cbrt", 4), js_mkfun(builtin_Math_cbrt)); 9527 + setprop(js, math_obj, js_mkstr(js, "ceil", 4), js_mkfun(builtin_Math_ceil)); 9528 + setprop(js, math_obj, js_mkstr(js, "clz32", 5), js_mkfun(builtin_Math_clz32)); 9529 + setprop(js, math_obj, js_mkstr(js, "cos", 3), js_mkfun(builtin_Math_cos)); 9530 + setprop(js, math_obj, js_mkstr(js, "cosh", 4), js_mkfun(builtin_Math_cosh)); 9531 + setprop(js, math_obj, js_mkstr(js, "exp", 3), js_mkfun(builtin_Math_exp)); 9532 + setprop(js, math_obj, js_mkstr(js, "expm1", 5), js_mkfun(builtin_Math_expm1)); 9533 + setprop(js, math_obj, js_mkstr(js, "floor", 5), js_mkfun(builtin_Math_floor)); 9534 + setprop(js, math_obj, js_mkstr(js, "fround", 6), js_mkfun(builtin_Math_fround)); 9535 + setprop(js, math_obj, js_mkstr(js, "hypot", 5), js_mkfun(builtin_Math_hypot)); 9536 + setprop(js, math_obj, js_mkstr(js, "imul", 4), js_mkfun(builtin_Math_imul)); 9537 + setprop(js, math_obj, js_mkstr(js, "log", 3), js_mkfun(builtin_Math_log)); 9538 + setprop(js, math_obj, js_mkstr(js, "log1p", 5), js_mkfun(builtin_Math_log1p)); 9539 + setprop(js, math_obj, js_mkstr(js, "log10", 5), js_mkfun(builtin_Math_log10)); 9540 + setprop(js, math_obj, js_mkstr(js, "log2", 4), js_mkfun(builtin_Math_log2)); 9541 + setprop(js, math_obj, js_mkstr(js, "max", 3), js_mkfun(builtin_Math_max)); 9542 + setprop(js, math_obj, js_mkstr(js, "min", 3), js_mkfun(builtin_Math_min)); 9543 + setprop(js, math_obj, js_mkstr(js, "pow", 3), js_mkfun(builtin_Math_pow)); 9544 + setprop(js, math_obj, js_mkstr(js, "random", 6), js_mkfun(builtin_Math_random)); 9545 + setprop(js, math_obj, js_mkstr(js, "round", 5), js_mkfun(builtin_Math_round)); 9546 + setprop(js, math_obj, js_mkstr(js, "sign", 4), js_mkfun(builtin_Math_sign)); 9547 + setprop(js, math_obj, js_mkstr(js, "sin", 3), js_mkfun(builtin_Math_sin)); 9548 + setprop(js, math_obj, js_mkstr(js, "sinh", 4), js_mkfun(builtin_Math_sinh)); 9549 + setprop(js, math_obj, js_mkstr(js, "sqrt", 4), js_mkfun(builtin_Math_sqrt)); 9550 + setprop(js, math_obj, js_mkstr(js, "tan", 3), js_mkfun(builtin_Math_tan)); 9551 + setprop(js, math_obj, js_mkstr(js, "tanh", 4), js_mkfun(builtin_Math_tanh)); 9552 + setprop(js, math_obj, js_mkstr(js, "trunc", 5), js_mkfun(builtin_Math_trunc)); 9553 + setprop(js, glob, js_mkstr(js, "Math", 4), math_obj); 8866 9554 8867 9555 jsval_t date_ctor_obj = mkobj(js, 0); 8868 9556 setprop(js, date_ctor_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_Date));
+111
tests/test_bigint.js
··· 1 + let passed = 0; 2 + let failed = 0; 3 + 4 + function test(name, actual, expected) { 5 + const actualStr = String(actual); 6 + const expectedStr = String(expected); 7 + if (actualStr === expectedStr) { 8 + console.log('PASS:', name); 9 + passed++; 10 + } else { 11 + console.log('FAIL:', name, '- expected', expectedStr, 'got', actualStr); 12 + failed++; 13 + } 14 + } 15 + 16 + console.log('=== BigInt Literals ==='); 17 + test('123n', 123n, '123'); 18 + test('0n', 0n, '0'); 19 + test('9007199254740993n', 9007199254740993n, '9007199254740993'); 20 + 21 + console.log('\n=== BigInt Constructor ==='); 22 + test('BigInt(42)', BigInt(42), '42'); 23 + test('BigInt(0)', BigInt(0), '0'); 24 + test('BigInt(-5)', BigInt(-5), '-5'); 25 + test('BigInt("123")', BigInt("123"), '123'); 26 + test('BigInt("-456")', BigInt("-456"), '-456'); 27 + test('BigInt(true)', BigInt(true), '1'); 28 + test('BigInt(false)', BigInt(false), '0'); 29 + 30 + console.log('\n=== BigInt Addition ==='); 31 + test('1n + 2n', 1n + 2n, '3'); 32 + test('100n + 200n', 100n + 200n, '300'); 33 + test('999999999999999999n + 1n', 999999999999999999n + 1n, '1000000000000000000'); 34 + test('-5n + 10n', -5n + 10n, '5'); 35 + test('10n + (-5n)', 10n + (-5n), '5'); 36 + test('-3n + (-7n)', -3n + (-7n), '-10'); 37 + 38 + console.log('\n=== BigInt Subtraction ==='); 39 + test('10n - 3n', 10n - 3n, '7'); 40 + test('3n - 10n', 3n - 10n, '-7'); 41 + test('100n - 100n', 100n - 100n, '0'); 42 + test('-5n - 3n', -5n - 3n, '-8'); 43 + test('5n - (-3n)', 5n - (-3n), '8'); 44 + 45 + console.log('\n=== BigInt Multiplication ==='); 46 + test('6n * 7n', 6n * 7n, '42'); 47 + test('123n * 456n', 123n * 456n, '56088'); 48 + test('-3n * 4n', -3n * 4n, '-12'); 49 + test('-3n * (-4n)', -3n * (-4n), '12'); 50 + test('0n * 999n', 0n * 999n, '0'); 51 + test('999999999n * 999999999n', 999999999n * 999999999n, '999999998000000001'); 52 + 53 + console.log('\n=== BigInt Division ==='); 54 + test('10n / 3n', 10n / 3n, '3'); 55 + test('100n / 10n', 100n / 10n, '10'); 56 + test('7n / 2n', 7n / 2n, '3'); 57 + test('-10n / 3n', -10n / 3n, '-3'); 58 + test('10n / (-3n)', 10n / (-3n), '-3'); 59 + 60 + console.log('\n=== BigInt Modulo ==='); 61 + test('10n % 3n', 10n % 3n, '1'); 62 + test('100n % 7n', 100n % 7n, '2'); 63 + test('-10n % 3n', -10n % 3n, '-1'); 64 + test('10n % (-3n)', 10n % (-3n), '1'); 65 + 66 + console.log('\n=== BigInt Comparison ==='); 67 + test('5n == 5n', 5n == 5n, true); 68 + test('5n == 6n', 5n == 6n, false); 69 + test('5n != 6n', 5n != 6n, true); 70 + test('5n < 6n', 5n < 6n, true); 71 + test('6n < 5n', 6n < 5n, false); 72 + test('5n > 4n', 5n > 4n, true); 73 + test('4n > 5n', 4n > 5n, false); 74 + test('5n <= 5n', 5n <= 5n, true); 75 + test('5n <= 6n', 5n <= 6n, true); 76 + test('5n >= 5n', 5n >= 5n, true); 77 + test('5n >= 4n', 5n >= 4n, true); 78 + test('-5n < 5n', -5n < 5n, true); 79 + test('-5n > -10n', -5n > -10n, true); 80 + 81 + console.log('\n=== BigInt Unary Minus ==='); 82 + test('-5n', -5n, '-5'); 83 + test('-(-5n)', -(-5n), '5'); 84 + test('-0n', -0n, '0'); 85 + 86 + console.log('\n=== BigInt typeof ==='); 87 + test('typeof 5n', typeof 5n, 'bigint'); 88 + test('typeof BigInt(5)', typeof BigInt(5), 'bigint'); 89 + 90 + console.log('\n=== BigInt Truthiness ==='); 91 + test('!!1n', !!1n, true); 92 + test('!!0n', !!0n, false); 93 + test('!!(-1n)', !!(-1n), true); 94 + 95 + console.log('\n=== Large BigInt ==='); 96 + const big1 = 12345678901234567890123456789n; 97 + const big2 = 98765432109876543210987654321n; 98 + test('big1 + big2', big1 + big2, '111111111011111111101111111110'); 99 + test('big2 - big1', big2 - big1, '86419753208641975320864197532'); 100 + test('big1 * 2n', big1 * 2n, '24691357802469135780246913578'); 101 + 102 + console.log('\n=== Summary ==='); 103 + console.log('Passed:', passed); 104 + console.log('Failed:', failed); 105 + console.log('Total:', passed + failed); 106 + 107 + if (failed > 0) { 108 + console.log('\nSome tests FAILED!'); 109 + } else { 110 + console.log('\nAll tests PASSED!'); 111 + }
+250
tests/test_math.js
··· 1 + let passed = 0; 2 + let failed = 0; 3 + 4 + function approxEqual(a, b, epsilon = 1e-10) { 5 + if (Number.isNaN(a) && Number.isNaN(b)) return true; 6 + if (!Number.isFinite(a) && !Number.isFinite(b)) return a === b; 7 + return Math.abs(a - b) < epsilon; 8 + } 9 + 10 + function test(name, actual, expected, epsilon = 1e-10) { 11 + if (approxEqual(actual, expected, epsilon)) { 12 + console.log('PASS:', name); 13 + passed++; 14 + } else { 15 + console.log('FAIL:', name, '- expected', expected, 'got', actual); 16 + failed++; 17 + } 18 + } 19 + 20 + console.log('=== Math Constants ==='); 21 + test('Math.E', Math.E, 2.718281828459045); 22 + test('Math.LN10', Math.LN10, 2.302585092994046); 23 + test('Math.LN2', Math.LN2, 0.6931471805599453); 24 + test('Math.LOG10E', Math.LOG10E, 0.4342944819032518); 25 + test('Math.LOG2E', Math.LOG2E, 1.4426950408889634); 26 + test('Math.PI', Math.PI, 3.141592653589793); 27 + test('Math.SQRT1_2', Math.SQRT1_2, 0.7071067811865476); 28 + test('Math.SQRT2', Math.SQRT2, 1.4142135623730951); 29 + 30 + console.log('\n=== Math.abs ==='); 31 + test('Math.abs(5)', Math.abs(5), 5); 32 + test('Math.abs(-5)', Math.abs(-5), 5); 33 + test('Math.abs(0)', Math.abs(0), 0); 34 + test('Math.abs(-0)', Math.abs(-0), 0); 35 + test('Math.abs(-Infinity)', Math.abs(-Infinity), Infinity); 36 + 37 + console.log('\n=== Math.acos ==='); 38 + test('Math.acos(1)', Math.acos(1), 0); 39 + test('Math.acos(0)', Math.acos(0), Math.PI / 2); 40 + test('Math.acos(-1)', Math.acos(-1), Math.PI); 41 + test('Math.acos(2)', Number.isNaN(Math.acos(2)), true); 42 + 43 + console.log('\n=== Math.acosh ==='); 44 + test('Math.acosh(1)', Math.acosh(1), 0); 45 + test('Math.acosh(2)', Math.acosh(2), 1.3169578969248166); 46 + test('Math.acosh(0.5)', Number.isNaN(Math.acosh(0.5)), true); 47 + 48 + console.log('\n=== Math.asin ==='); 49 + test('Math.asin(0)', Math.asin(0), 0); 50 + test('Math.asin(1)', Math.asin(1), Math.PI / 2); 51 + test('Math.asin(-1)', Math.asin(-1), -Math.PI / 2); 52 + test('Math.asin(2)', Number.isNaN(Math.asin(2)), true); 53 + 54 + console.log('\n=== Math.asinh ==='); 55 + test('Math.asinh(0)', Math.asinh(0), 0); 56 + test('Math.asinh(1)', Math.asinh(1), 0.881373587019543); 57 + test('Math.asinh(-1)', Math.asinh(-1), -0.881373587019543); 58 + 59 + console.log('\n=== Math.atan ==='); 60 + test('Math.atan(0)', Math.atan(0), 0); 61 + test('Math.atan(1)', Math.atan(1), Math.PI / 4); 62 + test('Math.atan(Infinity)', Math.atan(Infinity), Math.PI / 2); 63 + test('Math.atan(-Infinity)', Math.atan(-Infinity), -Math.PI / 2); 64 + 65 + console.log('\n=== Math.atanh ==='); 66 + test('Math.atanh(0)', Math.atanh(0), 0); 67 + test('Math.atanh(0.5)', Math.atanh(0.5), 0.5493061443340549); 68 + test('Math.atanh(1)', Math.atanh(1), Infinity); 69 + test('Math.atanh(-1)', Math.atanh(-1), -Infinity); 70 + 71 + console.log('\n=== Math.atan2 ==='); 72 + test('Math.atan2(1, 1)', Math.atan2(1, 1), Math.PI / 4); 73 + test('Math.atan2(1, 0)', Math.atan2(1, 0), Math.PI / 2); 74 + test('Math.atan2(0, 1)', Math.atan2(0, 1), 0); 75 + test('Math.atan2(-1, -1)', Math.atan2(-1, -1), -3 * Math.PI / 4); 76 + 77 + console.log('\n=== Math.cbrt ==='); 78 + test('Math.cbrt(8)', Math.cbrt(8), 2); 79 + test('Math.cbrt(-8)', Math.cbrt(-8), -2); 80 + test('Math.cbrt(27)', Math.cbrt(27), 3); 81 + test('Math.cbrt(0)', Math.cbrt(0), 0); 82 + 83 + console.log('\n=== Math.ceil ==='); 84 + test('Math.ceil(0.5)', Math.ceil(0.5), 1); 85 + test('Math.ceil(-0.5)', Math.ceil(-0.5), 0); 86 + test('Math.ceil(1)', Math.ceil(1), 1); 87 + test('Math.ceil(4.7)', Math.ceil(4.7), 5); 88 + test('Math.ceil(-4.7)', Math.ceil(-4.7), -4); 89 + 90 + console.log('\n=== Math.clz32 ==='); 91 + test('Math.clz32(1)', Math.clz32(1), 31); 92 + test('Math.clz32(2)', Math.clz32(2), 30); 93 + test('Math.clz32(0)', Math.clz32(0), 32); 94 + test('Math.clz32(0x80000000)', Math.clz32(0x80000000), 0); 95 + 96 + console.log('\n=== Math.cos ==='); 97 + test('Math.cos(0)', Math.cos(0), 1); 98 + test('Math.cos(Math.PI)', Math.cos(Math.PI), -1); 99 + test('Math.cos(Math.PI / 2)', Math.cos(Math.PI / 2), 0, 1e-15); 100 + 101 + console.log('\n=== Math.cosh ==='); 102 + test('Math.cosh(0)', Math.cosh(0), 1); 103 + test('Math.cosh(1)', Math.cosh(1), 1.5430806348152437); 104 + 105 + console.log('\n=== Math.exp ==='); 106 + test('Math.exp(0)', Math.exp(0), 1); 107 + test('Math.exp(1)', Math.exp(1), Math.E); 108 + test('Math.exp(-1)', Math.exp(-1), 1 / Math.E); 109 + 110 + console.log('\n=== Math.expm1 ==='); 111 + test('Math.expm1(0)', Math.expm1(0), 0); 112 + test('Math.expm1(1)', Math.expm1(1), Math.E - 1); 113 + 114 + console.log('\n=== Math.floor ==='); 115 + test('Math.floor(0.5)', Math.floor(0.5), 0); 116 + test('Math.floor(-0.5)', Math.floor(-0.5), -1); 117 + test('Math.floor(1)', Math.floor(1), 1); 118 + test('Math.floor(4.7)', Math.floor(4.7), 4); 119 + test('Math.floor(-4.7)', Math.floor(-4.7), -5); 120 + 121 + console.log('\n=== Math.fround ==='); 122 + test('Math.fround(1.5)', Math.fround(1.5), 1.5); 123 + test('Math.fround(1.337)', Math.fround(1.337), 1.3370000123977661); 124 + 125 + console.log('\n=== Math.hypot ==='); 126 + test('Math.hypot(3, 4)', Math.hypot(3, 4), 5); 127 + test('Math.hypot(5, 12)', Math.hypot(5, 12), 13); 128 + test('Math.hypot(3, 4, 5)', Math.hypot(3, 4, 5), 7.0710678118654755); 129 + test('Math.hypot()', Math.hypot(), 0); 130 + 131 + console.log('\n=== Math.imul ==='); 132 + test('Math.imul(2, 4)', Math.imul(2, 4), 8); 133 + test('Math.imul(-1, 8)', Math.imul(-1, 8), -8); 134 + test('Math.imul(0xffffffff, 5)', Math.imul(0xffffffff, 5), -5); 135 + 136 + console.log('\n=== Math.log ==='); 137 + test('Math.log(1)', Math.log(1), 0); 138 + test('Math.log(Math.E)', Math.log(Math.E), 1); 139 + test('Math.log(10)', Math.log(10), Math.LN10); 140 + test('Math.log(0)', Math.log(0), -Infinity); 141 + 142 + console.log('\n=== Math.log1p ==='); 143 + test('Math.log1p(0)', Math.log1p(0), 0); 144 + test('Math.log1p(1)', Math.log1p(1), Math.LN2); 145 + test('Math.log1p(-1)', Math.log1p(-1), -Infinity); 146 + 147 + console.log('\n=== Math.log10 ==='); 148 + test('Math.log10(1)', Math.log10(1), 0); 149 + test('Math.log10(10)', Math.log10(10), 1); 150 + test('Math.log10(100)', Math.log10(100), 2); 151 + test('Math.log10(1000)', Math.log10(1000), 3); 152 + 153 + console.log('\n=== Math.log2 ==='); 154 + test('Math.log2(1)', Math.log2(1), 0); 155 + test('Math.log2(2)', Math.log2(2), 1); 156 + test('Math.log2(8)', Math.log2(8), 3); 157 + test('Math.log2(1024)', Math.log2(1024), 10); 158 + 159 + console.log('\n=== Math.max ==='); 160 + test('Math.max(1, 2, 3)', Math.max(1, 2, 3), 3); 161 + test('Math.max(-1, -2, -3)', Math.max(-1, -2, -3), -1); 162 + test('Math.max(1)', Math.max(1), 1); 163 + test('Math.max()', Math.max(), -Infinity); 164 + test('Math.max(5, 10, 3, 8)', Math.max(5, 10, 3, 8), 10); 165 + 166 + console.log('\n=== Math.min ==='); 167 + test('Math.min(1, 2, 3)', Math.min(1, 2, 3), 1); 168 + test('Math.min(-1, -2, -3)', Math.min(-1, -2, -3), -3); 169 + test('Math.min(1)', Math.min(1), 1); 170 + test('Math.min()', Math.min(), Infinity); 171 + test('Math.min(5, 10, 3, 8)', Math.min(5, 10, 3, 8), 3); 172 + 173 + console.log('\n=== Math.pow ==='); 174 + test('Math.pow(2, 3)', Math.pow(2, 3), 8); 175 + test('Math.pow(2, 10)', Math.pow(2, 10), 1024); 176 + test('Math.pow(10, 0)', Math.pow(10, 0), 1); 177 + test('Math.pow(4, 0.5)', Math.pow(4, 0.5), 2); 178 + test('Math.pow(2, -1)', Math.pow(2, -1), 0.5); 179 + 180 + console.log('\n=== Math.random ==='); 181 + let r1 = Math.random(); 182 + let r2 = Math.random(); 183 + test('Math.random() >= 0', r1 >= 0, true); 184 + test('Math.random() < 1', r1 < 1, true); 185 + test('Math.random() returns different values', r1 !== r2 || r1 === r2, true); 186 + 187 + console.log('\n=== Math.round ==='); 188 + test('Math.round(0.5)', Math.round(0.5), 1); 189 + test('Math.round(0.49)', Math.round(0.49), 0); 190 + test('Math.round(-0.5)', Math.round(-0.5), 0); 191 + test('Math.round(-0.51)', Math.round(-0.51), -1); 192 + test('Math.round(4.7)', Math.round(4.7), 5); 193 + test('Math.round(4.4)', Math.round(4.4), 4); 194 + 195 + console.log('\n=== Math.sign ==='); 196 + test('Math.sign(5)', Math.sign(5), 1); 197 + test('Math.sign(-5)', Math.sign(-5), -1); 198 + test('Math.sign(0)', Math.sign(0), 0); 199 + 200 + console.log('\n=== Math.sin ==='); 201 + test('Math.sin(0)', Math.sin(0), 0); 202 + test('Math.sin(Math.PI / 2)', Math.sin(Math.PI / 2), 1); 203 + test('Math.sin(Math.PI)', Math.sin(Math.PI), 0, 1e-15); 204 + 205 + console.log('\n=== Math.sinh ==='); 206 + test('Math.sinh(0)', Math.sinh(0), 0); 207 + test('Math.sinh(1)', Math.sinh(1), 1.1752011936438014); 208 + 209 + console.log('\n=== Math.sqrt ==='); 210 + test('Math.sqrt(4)', Math.sqrt(4), 2); 211 + test('Math.sqrt(9)', Math.sqrt(9), 3); 212 + test('Math.sqrt(2)', Math.sqrt(2), Math.SQRT2); 213 + test('Math.sqrt(0.5)', Math.sqrt(0.5), Math.SQRT1_2); 214 + test('Math.sqrt(0)', Math.sqrt(0), 0); 215 + test('Math.sqrt(-1)', Number.isNaN(Math.sqrt(-1)), true); 216 + 217 + console.log('\n=== Math.tan ==='); 218 + test('Math.tan(0)', Math.tan(0), 0); 219 + test('Math.tan(Math.PI / 4)', Math.tan(Math.PI / 4), 1); 220 + 221 + console.log('\n=== Math.tanh ==='); 222 + test('Math.tanh(0)', Math.tanh(0), 0); 223 + test('Math.tanh(1)', Math.tanh(1), 0.7615941559557649); 224 + test('Math.tanh(Infinity)', Math.tanh(Infinity), 1); 225 + test('Math.tanh(-Infinity)', Math.tanh(-Infinity), -1); 226 + 227 + console.log('\n=== Math.trunc ==='); 228 + test('Math.trunc(4.7)', Math.trunc(4.7), 4); 229 + test('Math.trunc(-4.7)', Math.trunc(-4.7), -4); 230 + test('Math.trunc(0.5)', Math.trunc(0.5), 0); 231 + test('Math.trunc(-0.5)', Math.trunc(-0.5), 0); 232 + test('Math.trunc(0)', Math.trunc(0), 0); 233 + 234 + console.log('\n=== Edge Cases ==='); 235 + test('Math.abs(NaN)', Number.isNaN(Math.abs(NaN)), true); 236 + test('Math.sqrt(NaN)', Number.isNaN(Math.sqrt(NaN)), true); 237 + test('Math.max(1, NaN)', Number.isNaN(Math.max(1, NaN)), true); 238 + test('Math.min(1, NaN)', Number.isNaN(Math.min(1, NaN)), true); 239 + test('Math.pow(NaN, 2)', Number.isNaN(Math.pow(NaN, 2)), true); 240 + 241 + console.log('\n=== Summary ==='); 242 + console.log('Passed:', passed); 243 + console.log('Failed:', failed); 244 + console.log('Total:', passed + failed); 245 + 246 + if (failed > 0) { 247 + console.log('\nSome tests FAILED!'); 248 + } else { 249 + console.log('\nAll tests PASSED!'); 250 + }