xbintsc 0.2.8 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -2
- package/README.zh-CN.md +16 -2
- package/bin/xbintsc.js +49 -10
- package/dist/src/ast/expressions.d.ts +2 -0
- package/dist/src/binder/binder.d.ts +24 -98
- package/dist/src/binder/binder.js +13 -559
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +16 -0
- package/dist/src/binder/declarations.js +168 -0
- package/dist/src/binder/declarations.js.map +1 -0
- package/dist/src/binder/helpers.d.ts +11 -0
- package/dist/src/binder/helpers.js +46 -0
- package/dist/src/binder/helpers.js.map +1 -0
- package/dist/src/binder/references.d.ts +21 -0
- package/dist/src/binder/references.js +349 -0
- package/dist/src/binder/references.js.map +1 -0
- package/dist/src/binder/types.d.ts +114 -0
- package/dist/src/binder/types.js +27 -0
- package/dist/src/binder/types.js.map +1 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +40 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.d.ts +13 -0
- package/dist/src/codegen/generator/calls/access.js +115 -0
- package/dist/src/codegen/generator/calls/access.js.map +1 -0
- package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
- package/dist/src/codegen/generator/calls/closures.js +50 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -0
- package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
- package/dist/src/codegen/generator/calls/invocation.js +242 -0
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
- package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
- package/dist/src/codegen/generator/calls/literals.js +69 -0
- package/dist/src/codegen/generator/calls/literals.js.map +1 -0
- package/dist/src/codegen/generator/calls/super.d.ts +10 -0
- package/dist/src/codegen/generator/calls/super.js +47 -0
- package/dist/src/codegen/generator/calls/super.js.map +1 -0
- package/dist/src/codegen/generator/calls.d.ts +15 -24
- package/dist/src/codegen/generator/calls.js +15 -482
- package/dist/src/codegen/generator/calls.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +1 -1
- package/dist/src/codegen/generator/context.js +2 -2
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
- package/dist/src/codegen/generator/expressions/assignment.js +203 -0
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
- package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
- package/dist/src/codegen/generator/expressions/operators.js +163 -0
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
- package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
- package/dist/src/codegen/generator/expressions/primary.js +260 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +11 -21
- package/dist/src/codegen/generator/expressions.js +11 -494
- package/dist/src/codegen/generator/expressions.js.map +1 -1
- package/dist/src/codegen/generator/module.js +16 -4
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +8 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
- package/dist/src/codegen/generator/statements/control-flow.js +199 -0
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
- package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
- package/dist/src/codegen/generator/statements/dispatch.js +100 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
- package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
- package/dist/src/codegen/generator/statements/loops.js +152 -0
- package/dist/src/codegen/generator/statements/loops.js.map +1 -0
- package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
- package/dist/src/codegen/generator/statements/variables.js +146 -0
- package/dist/src/codegen/generator/statements/variables.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +13 -21
- package/dist/src/codegen/generator/statements.js +13 -568
- package/dist/src/codegen/generator/statements.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +7 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/codegen/values.d.ts +17 -17
- package/dist/src/codegen/values.js +21 -57
- package/dist/src/codegen/values.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +1 -0
- package/dist/src/diagnostics/diagnostic.js +1 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/diagnostics/source.d.ts +1 -1
- package/dist/src/diagnostics/source.js +7 -12
- package/dist/src/diagnostics/source.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +4 -0
- package/dist/src/driver/compiler.js +51 -16
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/index.d.ts +5 -2
- package/dist/src/driver/index.js +5 -2
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/paths.d.ts +20 -0
- package/dist/src/driver/paths.js +49 -0
- package/dist/src/driver/paths.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +18 -0
- package/dist/src/driver/runtime-lib.js +31 -0
- package/dist/src/driver/runtime-lib.js.map +1 -0
- package/dist/src/driver/toolchain-download.d.ts +50 -0
- package/dist/src/driver/toolchain-download.js +76 -0
- package/dist/src/driver/toolchain-download.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +33 -0
- package/dist/src/driver/toolchain-provider.js +71 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -0
- package/dist/src/driver/toolchain.d.ts +9 -4
- package/dist/src/driver/toolchain.js +6 -10
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/extensions/node/child_process/index.d.ts +4 -2
- package/dist/src/extensions/node/child_process/index.js +4 -2
- package/dist/src/extensions/node/child_process/index.js.map +1 -1
- package/dist/src/extensions/node/events/index.d.ts +10 -0
- package/dist/src/extensions/node/events/index.js +22 -0
- package/dist/src/extensions/node/events/index.js.map +1 -0
- package/dist/src/extensions/node/index.js +6 -0
- package/dist/src/extensions/node/index.js.map +1 -1
- package/dist/src/extensions/node/querystring/index.d.ts +10 -0
- package/dist/src/extensions/node/querystring/index.js +25 -0
- package/dist/src/extensions/node/querystring/index.js.map +1 -0
- package/dist/src/extensions/node/util/index.d.ts +11 -0
- package/dist/src/extensions/node/util/index.js +41 -0
- package/dist/src/extensions/node/util/index.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +6 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
- package/dist/src/lexer/scanner/identifiers.js +33 -0
- package/dist/src/lexer/scanner/identifiers.js.map +1 -0
- package/dist/src/lexer/scanner/numbers.d.ts +10 -0
- package/dist/src/lexer/scanner/numbers.js +89 -0
- package/dist/src/lexer/scanner/numbers.js.map +1 -0
- package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
- package/dist/src/lexer/scanner/punctuation.js +151 -0
- package/dist/src/lexer/scanner/punctuation.js.map +1 -0
- package/dist/src/lexer/scanner/regex.d.ts +11 -0
- package/dist/src/lexer/scanner/regex.js +69 -0
- package/dist/src/lexer/scanner/regex.js.map +1 -0
- package/dist/src/lexer/scanner/strings.d.ts +13 -0
- package/dist/src/lexer/scanner/strings.js +118 -0
- package/dist/src/lexer/scanner/strings.js.map +1 -0
- package/dist/src/lexer/scanner.d.ts +20 -27
- package/dist/src/lexer/scanner.js +11 -415
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/declarations/classes.d.ts +14 -0
- package/dist/src/parser/declarations/classes.js +191 -0
- package/dist/src/parser/declarations/classes.js.map +1 -0
- package/dist/src/parser/declarations/functions.d.ts +17 -0
- package/dist/src/parser/declarations/functions.js +241 -0
- package/dist/src/parser/declarations/functions.js.map +1 -0
- package/dist/src/parser/declarations/type-members.d.ts +16 -0
- package/dist/src/parser/declarations/type-members.js +156 -0
- package/dist/src/parser/declarations/type-members.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +13 -24
- package/dist/src/parser/declarations.js +13 -571
- package/dist/src/parser/declarations.js.map +1 -1
- package/dist/src/parser/helpers.js +13 -4
- package/dist/src/parser/helpers.js.map +1 -1
- package/dist/src/parser/literals.js +10 -1
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +24 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +3 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/paths.test.d.ts +1 -0
- package/dist/tests/driver/paths.test.js +26 -0
- package/dist/tests/driver/paths.test.js.map +1 -0
- package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-download.test.js +38 -0
- package/dist/tests/driver/toolchain-download.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +37 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
- package/dist/tests/e2e/compile-node.test.d.ts +7 -0
- package/dist/tests/e2e/compile-node.test.js +123 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -0
- package/dist/tests/e2e/compile.test.d.ts +4 -1
- package/dist/tests/e2e/compile.test.js +90 -130
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/harness.d.ts +36 -0
- package/dist/tests/e2e/harness.js +64 -0
- package/dist/tests/e2e/harness.js.map +1 -0
- package/dist/tests/e2e/node-modules.test.js +60 -0
- package/dist/tests/e2e/node-modules.test.js.map +1 -1
- package/dist/tests/extensions/registry.test.js +4 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/package.json +5 -3
- package/runtime/ext_node/buffer/buffer.c +12 -552
- package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
- package/runtime/ext_node/buffer/parts/construction.inc +60 -0
- package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
- package/runtime/ext_node/buffer/parts/methods.inc +135 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
- package/runtime/ext_node/buffer/parts/search.inc +86 -0
- package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
- package/runtime/ext_node/child_process/child_process.c +37 -3
- package/runtime/ext_node/events/events.c +285 -0
- package/runtime/ext_node/http/http.c +11 -736
- package/runtime/ext_node/http/parts/client.inc +290 -0
- package/runtime/ext_node/http/parts/helpers.inc +45 -0
- package/runtime/ext_node/http/parts/prototypes.inc +57 -0
- package/runtime/ext_node/http/parts/response.inc +149 -0
- package/runtime/ext_node/http/parts/server.inc +133 -0
- package/runtime/ext_node/http/parts/string-builder.inc +58 -0
- package/runtime/ext_node/net/net.c +12 -504
- package/runtime/ext_node/net/parts/construction.inc +22 -0
- package/runtime/ext_node/net/parts/platform.inc +60 -0
- package/runtime/ext_node/net/parts/prototypes.inc +35 -0
- package/runtime/ext_node/net/parts/read-loop.inc +58 -0
- package/runtime/ext_node/net/parts/server.inc +131 -0
- package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
- package/runtime/ext_node/net/parts/static-api.inc +93 -0
- package/runtime/ext_node/querystring/querystring.c +251 -0
- package/runtime/ext_node/util/util.c +456 -0
- package/runtime/rt.h +8 -2
- package/runtime/rt_internal.h +34 -0
- package/runtime/xt_bigint/arithmetic.inc +135 -0
- package/runtime/xt_bigint/bits.inc +98 -0
- package/runtime/xt_bigint/bitwise.inc +103 -0
- package/runtime/xt_bigint/compare.inc +30 -0
- package/runtime/xt_bigint/conversions.inc +51 -0
- package/runtime/xt_bigint/division.inc +85 -0
- package/runtime/xt_bigint/format.inc +145 -0
- package/runtime/xt_bigint/helpers.inc +92 -0
- package/runtime/xt_bigint/magnitude.inc +88 -0
- package/runtime/xt_bigint/public.inc +59 -0
- package/runtime/xt_bigint/small-arithmetic.inc +58 -0
- package/runtime/xt_bigint.c +42 -0
- package/runtime/xt_builtins.c +40 -5
- package/runtime/xt_io.c +7 -0
- package/runtime/xt_stdlib/arrays.inc +161 -0
- package/runtime/xt_stdlib/dispatch.inc +116 -0
- package/runtime/xt_stdlib/helpers.inc +23 -0
- package/runtime/xt_stdlib/math.inc +72 -0
- package/runtime/xt_stdlib/strings.inc +178 -0
- package/runtime/xt_stdlib.c +10 -549
- package/runtime/xt_stdlib2/array-statics.inc +37 -0
- package/runtime/xt_stdlib2/arrays.inc +189 -0
- package/runtime/xt_stdlib2/container.inc +23 -0
- package/runtime/xt_stdlib2/date.inc +72 -0
- package/runtime/xt_stdlib2/error.inc +22 -0
- package/runtime/xt_stdlib2/helpers.inc +43 -0
- package/runtime/xt_stdlib2/json.inc +213 -0
- package/runtime/xt_stdlib2/map.inc +95 -0
- package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
- package/runtime/xt_stdlib2/numbers.inc +38 -0
- package/runtime/xt_stdlib2/objects.inc +41 -0
- package/runtime/xt_stdlib2/regexp-match.inc +204 -0
- package/runtime/xt_stdlib2/regexp.inc +20 -0
- package/runtime/xt_stdlib2/set.inc +105 -0
- package/runtime/xt_stdlib2/strings.inc +94 -0
- package/runtime/xt_stdlib2.c +19 -1278
- package/runtime/xt_values.c +155 -12
- package/scripts/build-runtime.ts +109 -0
- package/scripts/fetch-toolchain.ts +101 -0
- package/scripts/package-release.ts +192 -0
- package/src/ast/expressions.ts +2 -0
- package/src/binder/binder.ts +40 -725
- package/src/binder/declarations.ts +203 -0
- package/src/binder/helpers.ts +47 -0
- package/src/binder/references.ts +410 -0
- package/src/binder/types.ts +134 -0
- package/src/cli/main.ts +43 -0
- package/src/codegen/generator/calls/access.ts +139 -0
- package/src/codegen/generator/calls/closures.ts +60 -0
- package/src/codegen/generator/calls/invocation.ts +282 -0
- package/src/codegen/generator/calls/literals.ts +77 -0
- package/src/codegen/generator/calls/super.ts +61 -0
- package/src/codegen/generator/calls.ts +30 -552
- package/src/codegen/generator/context.ts +2 -2
- package/src/codegen/generator/expressions/assignment.ts +226 -0
- package/src/codegen/generator/expressions/operators.ts +182 -0
- package/src/codegen/generator/expressions/primary.ts +304 -0
- package/src/codegen/generator/expressions.ts +22 -553
- package/src/codegen/generator/module.ts +14 -4
- package/src/codegen/generator/state.ts +8 -0
- package/src/codegen/generator/statements/control-flow.ts +225 -0
- package/src/codegen/generator/statements/dispatch.ts +122 -0
- package/src/codegen/generator/statements/loops.ts +173 -0
- package/src/codegen/generator/statements/variables.ts +152 -0
- package/src/codegen/generator/statements.ts +26 -612
- package/src/codegen/generator/tables.ts +7 -0
- package/src/codegen/values.ts +22 -57
- package/src/diagnostics/diagnostic.ts +1 -0
- package/src/diagnostics/source.ts +7 -12
- package/src/driver/compiler.ts +61 -18
- package/src/driver/index.ts +17 -2
- package/src/driver/paths.ts +54 -0
- package/src/driver/runtime-lib.ts +32 -0
- package/src/driver/toolchain-download.ts +108 -0
- package/src/driver/toolchain-provider.ts +91 -0
- package/src/driver/toolchain.ts +29 -11
- package/src/extensions/node/child_process/index.ts +4 -2
- package/src/extensions/node/events/index.ts +27 -0
- package/src/extensions/node/index.ts +6 -0
- package/src/extensions/node/querystring/index.ts +29 -0
- package/src/extensions/node/util/index.ts +48 -0
- package/src/extensions/registry.ts +6 -0
- package/src/index.ts +1 -0
- package/src/lexer/scanner/identifiers.ts +37 -0
- package/src/lexer/scanner/numbers.ts +84 -0
- package/src/lexer/scanner/punctuation.ts +132 -0
- package/src/lexer/scanner/regex.ts +79 -0
- package/src/lexer/scanner/strings.ts +128 -0
- package/src/lexer/scanner.ts +35 -401
- package/src/parser/declarations/classes.ts +215 -0
- package/src/parser/declarations/functions.ts +254 -0
- package/src/parser/declarations/type-members.ts +181 -0
- package/src/parser/declarations.ts +32 -609
- package/src/parser/helpers.ts +13 -6
- package/src/parser/literals.ts +10 -1
- package/scripts/build-runtime.mjs +0 -55
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* -- bit access ------------------------------------------------------------ */
|
|
2
|
+
|
|
3
|
+
static uint32_t bi_clz32(uint32_t x) {
|
|
4
|
+
if (x == 0) return 32;
|
|
5
|
+
uint32_t count = 0;
|
|
6
|
+
while (!(x & 0x80000000u)) {
|
|
7
|
+
x <<= 1;
|
|
8
|
+
count++;
|
|
9
|
+
}
|
|
10
|
+
return count;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static uint32_t bi_bitlength(const xt_bigint *a) {
|
|
14
|
+
if (a->length == 0) return 0;
|
|
15
|
+
return (a->length - 1) * 32 + (32 - bi_clz32(a->limbs[a->length - 1]));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static int bi_get_bit(const xt_bigint *a, uint32_t index) {
|
|
19
|
+
uint32_t limb = index >> 5;
|
|
20
|
+
if (limb >= a->length) return 0;
|
|
21
|
+
return (a->limbs[limb] >> (index & 31)) & 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static void bi_set_bit(xt_bigint *a, uint32_t index) {
|
|
25
|
+
uint32_t limb = index >> 5;
|
|
26
|
+
if (limb >= a->length) {
|
|
27
|
+
bi_reserve(a, limb + 1);
|
|
28
|
+
for (uint32_t i = a->length; i <= limb; i++) a->limbs[i] = 0;
|
|
29
|
+
a->length = limb + 1;
|
|
30
|
+
}
|
|
31
|
+
a->limbs[limb] |= (uint32_t)1 << (index & 31);
|
|
32
|
+
a->sign = 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Shift the magnitude left by one bit, preserving the (magnitude) sign. */
|
|
36
|
+
static void bi_shl1_inplace(xt_bigint *a) {
|
|
37
|
+
if (a->length == 0) return;
|
|
38
|
+
bi_reserve(a, a->length + 1);
|
|
39
|
+
uint32_t carry = 0;
|
|
40
|
+
for (uint32_t i = 0; i < a->length; i++) {
|
|
41
|
+
uint32_t value = a->limbs[i];
|
|
42
|
+
a->limbs[i] = (value << 1) | carry;
|
|
43
|
+
carry = value >> 31;
|
|
44
|
+
}
|
|
45
|
+
if (carry) a->limbs[a->length++] = carry;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* -- shifts ---------------------------------------------------------------- */
|
|
49
|
+
|
|
50
|
+
static xt_bigint *bi_shl_bits(const xt_bigint *a, uint32_t bits) {
|
|
51
|
+
if (a->length == 0) return bi_zero();
|
|
52
|
+
uint32_t word = bits >> 5;
|
|
53
|
+
uint32_t shift = bits & 31;
|
|
54
|
+
xt_bigint *r = bi_alloc(a->length + word + 1);
|
|
55
|
+
if (shift == 0) {
|
|
56
|
+
for (uint32_t i = 0; i < a->length; i++) r->limbs[i + word] = a->limbs[i];
|
|
57
|
+
r->length = a->length + word;
|
|
58
|
+
} else {
|
|
59
|
+
uint32_t carry = 0;
|
|
60
|
+
for (uint32_t i = 0; i < a->length; i++) {
|
|
61
|
+
uint64_t cur = ((uint64_t)a->limbs[i] << shift) | carry;
|
|
62
|
+
r->limbs[i + word] = (uint32_t)cur;
|
|
63
|
+
carry = (uint32_t)(cur >> 32);
|
|
64
|
+
}
|
|
65
|
+
r->limbs[a->length + word] = carry;
|
|
66
|
+
r->length = a->length + word + (carry ? 1 : 0);
|
|
67
|
+
}
|
|
68
|
+
r->sign = a->sign;
|
|
69
|
+
bi_normalize(r);
|
|
70
|
+
if (r->length) r->sign = a->sign;
|
|
71
|
+
return r;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Logical right shift of a non-negative magnitude. */
|
|
75
|
+
static xt_bigint *bi_shr_bits(const xt_bigint *a, uint32_t bits) {
|
|
76
|
+
if ((uint64_t)bits >= (uint64_t)a->length * 32) return bi_zero();
|
|
77
|
+
uint32_t word = bits >> 5;
|
|
78
|
+
uint32_t shift = bits & 31;
|
|
79
|
+
uint32_t count = a->length - word;
|
|
80
|
+
xt_bigint *r = bi_alloc(count);
|
|
81
|
+
if (shift == 0) {
|
|
82
|
+
for (uint32_t i = 0; i < count; i++) r->limbs[i] = a->limbs[i + word];
|
|
83
|
+
r->length = count;
|
|
84
|
+
} else {
|
|
85
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
86
|
+
uint64_t low = (uint64_t)a->limbs[i + word] >> shift;
|
|
87
|
+
uint64_t high = (i + word + 1 < a->length)
|
|
88
|
+
? ((uint64_t)a->limbs[i + word + 1] << (32 - shift))
|
|
89
|
+
: 0;
|
|
90
|
+
r->limbs[i] = (uint32_t)(low | high);
|
|
91
|
+
}
|
|
92
|
+
r->length = count;
|
|
93
|
+
}
|
|
94
|
+
r->sign = 1;
|
|
95
|
+
bi_normalize(r);
|
|
96
|
+
return r;
|
|
97
|
+
}
|
|
98
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Bitwise operators */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
typedef enum { BI_AND, BI_OR, BI_XOR } bi_bitop;
|
|
6
|
+
|
|
7
|
+
static xt_value bi_bitwise(xt_value av, xt_value bv, bi_bitop op) {
|
|
8
|
+
const xt_bigint *a = BI(av);
|
|
9
|
+
const xt_bigint *b = BI(bv);
|
|
10
|
+
uint32_t count = (a->length > b->length ? a->length : b->length) + 1;
|
|
11
|
+
uint32_t *x = (uint32_t *)malloc((size_t)count * sizeof(uint32_t));
|
|
12
|
+
uint32_t *y = (uint32_t *)malloc((size_t)count * sizeof(uint32_t));
|
|
13
|
+
if (!x || !y) abort();
|
|
14
|
+
bi_to_twos(a, x, count);
|
|
15
|
+
bi_to_twos(b, y, count);
|
|
16
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
17
|
+
if (op == BI_AND) x[i] &= y[i];
|
|
18
|
+
else if (op == BI_OR) x[i] |= y[i];
|
|
19
|
+
else x[i] ^= y[i];
|
|
20
|
+
}
|
|
21
|
+
xt_bigint *r = bi_from_twos(x, count);
|
|
22
|
+
free(x);
|
|
23
|
+
free(y);
|
|
24
|
+
return bi_wrap(r);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
xt_value xt_bigint_bit_and(xt_value a, xt_value b) { return bi_bitwise(a, b, BI_AND); }
|
|
28
|
+
xt_value xt_bigint_bit_or(xt_value a, xt_value b) { return bi_bitwise(a, b, BI_OR); }
|
|
29
|
+
xt_value xt_bigint_bit_xor(xt_value a, xt_value b) { return bi_bitwise(a, b, BI_XOR); }
|
|
30
|
+
|
|
31
|
+
xt_value xt_bigint_bit_not(xt_value value) {
|
|
32
|
+
/* ~a === -a - 1. */
|
|
33
|
+
xt_value negated = xt_bigint_neg(value);
|
|
34
|
+
xt_value one = xt_bigint_from_i64(1);
|
|
35
|
+
return xt_bigint_sub(negated, one);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static int64_t bi_shift_count(xt_value value, int *overflow) {
|
|
39
|
+
const xt_bigint *b = BI(value);
|
|
40
|
+
*overflow = 0;
|
|
41
|
+
if (b->length == 0) return 0;
|
|
42
|
+
if (b->length > 2) {
|
|
43
|
+
*overflow = 1;
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
uint64_t magnitude = b->limbs[0];
|
|
47
|
+
if (b->length == 2) magnitude |= (uint64_t)b->limbs[1] << 32;
|
|
48
|
+
if (magnitude > (uint64_t)INT64_MAX) {
|
|
49
|
+
*overflow = 1;
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
return b->sign < 0 ? -(int64_t)magnitude : (int64_t)magnitude;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static xt_value bi_shl_count(xt_value value, uint32_t bits) {
|
|
56
|
+
if (bits > BI_MAX_SHIFT) {
|
|
57
|
+
bi_throw_range("Maximum BigInt size exceeded");
|
|
58
|
+
return bi_wrap(bi_zero());
|
|
59
|
+
}
|
|
60
|
+
xt_bigint *r = bi_shl_bits(BI(value), bits);
|
|
61
|
+
return bi_wrap(r);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static xt_value bi_shr_count(xt_value value, uint32_t bits) {
|
|
65
|
+
const xt_bigint *a = BI(value);
|
|
66
|
+
if (a->sign >= 0) {
|
|
67
|
+
xt_bigint *r = bi_shr_bits(a, bits);
|
|
68
|
+
if (r->length) r->sign = 1;
|
|
69
|
+
return bi_wrap(r);
|
|
70
|
+
}
|
|
71
|
+
/* Arithmetic shift of a negative value: -( ((|a| - 1) >> bits) + 1 ). */
|
|
72
|
+
xt_bigint *magnitude = bi_copy(a);
|
|
73
|
+
magnitude->sign = 1;
|
|
74
|
+
bi_sub_small(magnitude, 1);
|
|
75
|
+
xt_bigint *shifted = bi_shr_bits(magnitude, bits);
|
|
76
|
+
bi_add_small(shifted, 1);
|
|
77
|
+
shifted->sign = -1;
|
|
78
|
+
return bi_wrap(shifted);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
xt_value xt_bigint_shl(xt_value av, xt_value bv) {
|
|
82
|
+
int overflow = 0;
|
|
83
|
+
int64_t count = bi_shift_count(bv, &overflow);
|
|
84
|
+
if (overflow || count > (int64_t)BI_MAX_SHIFT) {
|
|
85
|
+
bi_throw_range("Maximum BigInt size exceeded");
|
|
86
|
+
return bi_wrap(bi_zero());
|
|
87
|
+
}
|
|
88
|
+
if (count < 0) return bi_shr_count(av, (uint32_t)(-count));
|
|
89
|
+
return bi_shl_count(av, (uint32_t)count);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
xt_value xt_bigint_shr(xt_value av, xt_value bv) {
|
|
93
|
+
int overflow = 0;
|
|
94
|
+
int64_t count = bi_shift_count(bv, &overflow);
|
|
95
|
+
if (overflow || count > (int64_t)BI_MAX_SHIFT) {
|
|
96
|
+
const xt_bigint *a = BI(av);
|
|
97
|
+
if (a->sign < 0) return xt_bigint_from_i64(-1);
|
|
98
|
+
return bi_wrap(bi_zero());
|
|
99
|
+
}
|
|
100
|
+
if (count < 0) return bi_shl_count(av, (uint32_t)(-count));
|
|
101
|
+
return bi_shr_count(av, (uint32_t)count);
|
|
102
|
+
}
|
|
103
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Comparisons */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
static int bi_cmp(const xt_bigint *a, const xt_bigint *b) {
|
|
6
|
+
if (a->sign != b->sign) return a->sign < b->sign ? -1 : 1;
|
|
7
|
+
if (a->sign == 0) return 0;
|
|
8
|
+
int cmp = bi_cmp_mag(a, b);
|
|
9
|
+
return a->sign < 0 ? -cmp : cmp;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
int xt_bigint_compare(xt_value a, xt_value b) { return bi_cmp(BI(a), BI(b)); }
|
|
13
|
+
|
|
14
|
+
int xt_bigint_compare_double(xt_value value, double other) {
|
|
15
|
+
const xt_bigint *a = BI(value);
|
|
16
|
+
if (isnan(other)) return 2;
|
|
17
|
+
if (isinf(other)) return other > 0 ? -1 : 1;
|
|
18
|
+
|
|
19
|
+
double truncated = trunc(other);
|
|
20
|
+
int otherSign = truncated == 0.0 ? 0 : (truncated < 0 ? -1 : 1);
|
|
21
|
+
xt_bigint *b = bi_from_abs_double(fabs(truncated));
|
|
22
|
+
if (b->length) b->sign = otherSign;
|
|
23
|
+
|
|
24
|
+
int cmp = bi_cmp(a, b);
|
|
25
|
+
if (other != truncated && cmp == 0) return other > truncated ? -1 : 1;
|
|
26
|
+
return cmp;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
int xt_is_bigint(xt_value value) { return XT_IS_BIGINT(value); }
|
|
30
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Conversions */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
double xt_bigint_to_double_value(xt_value value) {
|
|
6
|
+
const xt_bigint *b = BI(value);
|
|
7
|
+
double result = 0.0;
|
|
8
|
+
for (uint32_t i = b->length; i-- > 0;) result = result * 4294967296.0 + (double)b->limbs[i];
|
|
9
|
+
return b->sign < 0 ? -result : result;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static xt_bigint *bi_from_abs_double(double value) {
|
|
13
|
+
xt_bigint *r = bi_alloc(8);
|
|
14
|
+
uint32_t count = 0;
|
|
15
|
+
while (value >= 1.0) {
|
|
16
|
+
double remainder = fmod(value, 4294967296.0);
|
|
17
|
+
if (count >= r->capacity) bi_reserve(r, r->capacity * 2);
|
|
18
|
+
r->limbs[count++] = (uint32_t)remainder;
|
|
19
|
+
value = floor(value / 4294967296.0);
|
|
20
|
+
}
|
|
21
|
+
r->length = count;
|
|
22
|
+
r->sign = count ? 1 : 0;
|
|
23
|
+
bi_normalize(r);
|
|
24
|
+
return r;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
xt_value xt_bigint_from_double(double value) {
|
|
28
|
+
if (isnan(value) || isinf(value) || value != floor(value)) {
|
|
29
|
+
bi_throw_range("The number cannot be converted to a BigInt because it is not an integer");
|
|
30
|
+
return bi_wrap(bi_zero());
|
|
31
|
+
}
|
|
32
|
+
if (value == 0.0) return bi_wrap(bi_zero());
|
|
33
|
+
int negative = value < 0;
|
|
34
|
+
xt_bigint *r = bi_from_abs_double(negative ? -value : value);
|
|
35
|
+
if (r->length) r->sign = negative ? -1 : 1;
|
|
36
|
+
return bi_wrap(r);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static xt_value bi_from_xt_value(xt_value value) {
|
|
40
|
+
if (XT_IS_BIGINT(value)) return value;
|
|
41
|
+
if (XT_IS_NUMBER(value)) return xt_bigint_from_double(xt_to_double(value));
|
|
42
|
+
if (XT_IS_STRING(value)) {
|
|
43
|
+
xt_string *s = xt_as_string(value);
|
|
44
|
+
return xt_bigint_from_string(s->data, s->length);
|
|
45
|
+
}
|
|
46
|
+
if (value == XT_TRUE) return xt_bigint_from_i64(1);
|
|
47
|
+
if (value == XT_FALSE) return xt_bigint_from_i64(0);
|
|
48
|
+
bi_throw_type("Cannot convert value to a BigInt");
|
|
49
|
+
return bi_wrap(bi_zero());
|
|
50
|
+
}
|
|
51
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* -- division -------------------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static void bi_divmod_mag(const xt_bigint *a, const xt_bigint *b, xt_bigint **qout, xt_bigint **rout) {
|
|
4
|
+
if (b->length == 0) {
|
|
5
|
+
bi_throw_range("Division by zero");
|
|
6
|
+
*qout = bi_zero();
|
|
7
|
+
*rout = bi_zero();
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (bi_cmp_mag(a, b) < 0) {
|
|
11
|
+
*qout = bi_zero();
|
|
12
|
+
*rout = bi_copy(a);
|
|
13
|
+
if ((*rout)->length) (*rout)->sign = 1;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
xt_bigint *q = bi_zero();
|
|
17
|
+
xt_bigint *r = bi_zero();
|
|
18
|
+
int32_t start = (int32_t)bi_bitlength(a) - 1;
|
|
19
|
+
for (int32_t i = start; i >= 0; i--) {
|
|
20
|
+
bi_shl1_inplace(r);
|
|
21
|
+
if (bi_get_bit(a, (uint32_t)i)) {
|
|
22
|
+
if (r->length == 0) {
|
|
23
|
+
r->length = 1;
|
|
24
|
+
r->limbs[0] = 1;
|
|
25
|
+
} else {
|
|
26
|
+
r->limbs[0] |= 1;
|
|
27
|
+
}
|
|
28
|
+
r->sign = 1;
|
|
29
|
+
}
|
|
30
|
+
if (bi_cmp_mag(r, b) >= 0) {
|
|
31
|
+
bi_sub_mag_inplace(r, b);
|
|
32
|
+
bi_set_bit(q, (uint32_t)i);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
*qout = q;
|
|
36
|
+
*rout = r;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* -- two's complement (bitwise operators) ---------------------------------- */
|
|
40
|
+
|
|
41
|
+
static void bi_to_twos(const xt_bigint *b, uint32_t *out, uint32_t count) {
|
|
42
|
+
for (uint32_t i = 0; i < count; i++) out[i] = i < b->length ? b->limbs[i] : 0;
|
|
43
|
+
if (b->sign < 0) {
|
|
44
|
+
uint64_t carry = 1;
|
|
45
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
46
|
+
out[i] = ~out[i];
|
|
47
|
+
uint64_t sum = (uint64_t)out[i] + carry;
|
|
48
|
+
out[i] = (uint32_t)sum;
|
|
49
|
+
carry = sum >> 32;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static xt_bigint *bi_from_twos(const uint32_t *in, uint32_t count) {
|
|
55
|
+
xt_bigint *r = bi_alloc(count ? count : 1);
|
|
56
|
+
if (count == 0) return r;
|
|
57
|
+
if (!((in[count - 1] >> 31) & 1)) {
|
|
58
|
+
memcpy(r->limbs, in, (size_t)count * sizeof(uint32_t));
|
|
59
|
+
r->length = count;
|
|
60
|
+
r->sign = 1;
|
|
61
|
+
bi_normalize(r);
|
|
62
|
+
return r;
|
|
63
|
+
}
|
|
64
|
+
uint64_t carry = 1;
|
|
65
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
66
|
+
uint32_t value = ~in[i];
|
|
67
|
+
uint64_t sum = (uint64_t)value + carry;
|
|
68
|
+
r->limbs[i] = (uint32_t)sum;
|
|
69
|
+
carry = sum >> 32;
|
|
70
|
+
}
|
|
71
|
+
r->length = count;
|
|
72
|
+
r->sign = -1;
|
|
73
|
+
bi_normalize(r);
|
|
74
|
+
return r;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static xt_bigint *bi_from_unsigned(const uint32_t *in, uint32_t count) {
|
|
78
|
+
xt_bigint *r = bi_alloc(count ? count : 1);
|
|
79
|
+
if (count) memcpy(r->limbs, in, (size_t)count * sizeof(uint32_t));
|
|
80
|
+
r->length = count;
|
|
81
|
+
r->sign = count ? 1 : 0;
|
|
82
|
+
bi_normalize(r);
|
|
83
|
+
return r;
|
|
84
|
+
}
|
|
85
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Parsing and formatting */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
static int bi_digit_value(char c) {
|
|
6
|
+
if (c >= '0' && c <= '9') return c - '0';
|
|
7
|
+
if (c >= 'a' && c <= 'z') return c - 'a' + 10;
|
|
8
|
+
if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
|
9
|
+
return -1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
xt_value xt_bigint_from_string(const char *data, size_t len) {
|
|
13
|
+
size_t start = 0;
|
|
14
|
+
size_t end = len;
|
|
15
|
+
while (start < end && (data[start] == ' ' || data[start] == '\t' || data[start] == '\n' ||
|
|
16
|
+
data[start] == '\r' || data[start] == '\f' || data[start] == '\v'))
|
|
17
|
+
start++;
|
|
18
|
+
while (end > start && (data[end - 1] == ' ' || data[end - 1] == '\t' || data[end - 1] == '\n' ||
|
|
19
|
+
data[end - 1] == '\r' || data[end - 1] == '\f' || data[end - 1] == '\v'))
|
|
20
|
+
end--;
|
|
21
|
+
|
|
22
|
+
int sign = 1;
|
|
23
|
+
if (start < end && (data[start] == '+' || data[start] == '-')) {
|
|
24
|
+
if (data[start] == '-') sign = -1;
|
|
25
|
+
start++;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
int radix = 10;
|
|
29
|
+
int hadPrefix = 0;
|
|
30
|
+
if (start + 1 < end && data[start] == '0') {
|
|
31
|
+
char marker = data[start + 1];
|
|
32
|
+
if (marker == 'x' || marker == 'X') {
|
|
33
|
+
radix = 16;
|
|
34
|
+
start += 2;
|
|
35
|
+
hadPrefix = 1;
|
|
36
|
+
} else if (marker == 'o' || marker == 'O') {
|
|
37
|
+
radix = 8;
|
|
38
|
+
start += 2;
|
|
39
|
+
hadPrefix = 1;
|
|
40
|
+
} else if (marker == 'b' || marker == 'B') {
|
|
41
|
+
radix = 2;
|
|
42
|
+
start += 2;
|
|
43
|
+
hadPrefix = 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
xt_bigint *r = bi_zero();
|
|
48
|
+
size_t digits = 0;
|
|
49
|
+
for (size_t i = start; i < end; i++) {
|
|
50
|
+
char c = data[i];
|
|
51
|
+
if (c == '_') continue;
|
|
52
|
+
int digit = bi_digit_value(c);
|
|
53
|
+
if (digit < 0 || digit >= radix) {
|
|
54
|
+
bi_throw_syntax("Cannot convert to a BigInt");
|
|
55
|
+
return bi_wrap(bi_zero());
|
|
56
|
+
}
|
|
57
|
+
bi_mul_small(r, (uint32_t)radix);
|
|
58
|
+
bi_add_small(r, (uint32_t)digit);
|
|
59
|
+
digits++;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (digits == 0) {
|
|
63
|
+
if (hadPrefix) {
|
|
64
|
+
bi_throw_syntax("Cannot convert to a BigInt");
|
|
65
|
+
return bi_wrap(bi_zero());
|
|
66
|
+
}
|
|
67
|
+
return bi_wrap(bi_zero());
|
|
68
|
+
}
|
|
69
|
+
r->sign = sign;
|
|
70
|
+
bi_normalize(r);
|
|
71
|
+
if (r->length) r->sign = sign;
|
|
72
|
+
return bi_wrap(r);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static void bi_format_chunk(char *out, uint32_t value, int radix, int minDigits, int *written) {
|
|
76
|
+
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
77
|
+
char buffer[40];
|
|
78
|
+
int count = 0;
|
|
79
|
+
if (value == 0) {
|
|
80
|
+
buffer[count++] = '0';
|
|
81
|
+
} else {
|
|
82
|
+
while (value > 0) {
|
|
83
|
+
buffer[count++] = digits[value % (uint32_t)radix];
|
|
84
|
+
value /= (uint32_t)radix;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
while (count < minDigits) buffer[count++] = '0';
|
|
88
|
+
for (int i = 0; i < count; i++) out[i] = buffer[count - 1 - i];
|
|
89
|
+
*written = count;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static xt_value bi_to_string_radix(const xt_bigint *b, int radix, int negative) {
|
|
93
|
+
if (radix < 2 || radix > 36) {
|
|
94
|
+
bi_throw_range("toString() radix must be between 2 and 36");
|
|
95
|
+
return xt_string_from_cstr("0");
|
|
96
|
+
}
|
|
97
|
+
if (b->length == 0) return xt_string_from_cstr("0");
|
|
98
|
+
|
|
99
|
+
uint32_t chunk = 1;
|
|
100
|
+
int chunkDigits = 0;
|
|
101
|
+
while ((uint64_t)chunk * (uint32_t)radix <= 0xffffffffULL) {
|
|
102
|
+
chunk *= (uint32_t)radix;
|
|
103
|
+
chunkDigits++;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
xt_bigint *tmp = bi_copy(b);
|
|
107
|
+
tmp->sign = 1;
|
|
108
|
+
size_t capacity = 24;
|
|
109
|
+
uint32_t *parts = (uint32_t *)malloc(capacity * sizeof(uint32_t));
|
|
110
|
+
size_t count = 0;
|
|
111
|
+
while (tmp->length > 0) {
|
|
112
|
+
if (count + 1 > capacity) {
|
|
113
|
+
capacity *= 2;
|
|
114
|
+
parts = (uint32_t *)realloc(parts, capacity * sizeof(uint32_t));
|
|
115
|
+
}
|
|
116
|
+
parts[count++] = bi_divmod_small(tmp, chunk);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
size_t maxChars = (size_t)count * (size_t)chunkDigits + 2;
|
|
120
|
+
char *out = (char *)malloc(maxChars);
|
|
121
|
+
size_t length = 0;
|
|
122
|
+
if (negative) out[length++] = '-';
|
|
123
|
+
int first = 1;
|
|
124
|
+
for (size_t i = count; i-- > 0;) {
|
|
125
|
+
int written = 0;
|
|
126
|
+
bi_format_chunk(out + length, parts[i], radix, first ? 0 : chunkDigits, &written);
|
|
127
|
+
length += (size_t)written;
|
|
128
|
+
first = 0;
|
|
129
|
+
}
|
|
130
|
+
xt_value result = xt_string_new(out, length);
|
|
131
|
+
free(parts);
|
|
132
|
+
free(out);
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
xt_value xt_bigint_to_string_radix(xt_value value, int radix) {
|
|
137
|
+
const xt_bigint *b = BI(value);
|
|
138
|
+
return bi_to_string_radix(b, radix, b->sign < 0);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
xt_value xt_bigint_to_decimal(xt_value value) {
|
|
142
|
+
const xt_bigint *b = BI(value);
|
|
143
|
+
return bi_to_string_radix(b, 10, b->sign < 0);
|
|
144
|
+
}
|
|
145
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Allocation and basic helpers */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
static xt_bigint *bi_alloc(uint32_t capacity) {
|
|
6
|
+
if (capacity < 1) capacity = 1;
|
|
7
|
+
xt_bigint *b = (xt_bigint *)xt_alloc(sizeof(xt_bigint), XT_OBJECT_KIND_BIGINT);
|
|
8
|
+
b->sign = 0;
|
|
9
|
+
b->length = 0;
|
|
10
|
+
b->capacity = capacity;
|
|
11
|
+
b->limbs = (uint32_t *)calloc(capacity, sizeof(uint32_t));
|
|
12
|
+
if (!b->limbs) {
|
|
13
|
+
fprintf(stderr, "xbintsc: out of memory allocating bigint\n");
|
|
14
|
+
abort();
|
|
15
|
+
}
|
|
16
|
+
return b;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static void bi_reserve(xt_bigint *b, uint32_t capacity) {
|
|
20
|
+
if (capacity <= b->capacity) return;
|
|
21
|
+
uint32_t grown = b->capacity ? b->capacity : 1;
|
|
22
|
+
while (grown < capacity) grown *= 2;
|
|
23
|
+
uint32_t *limbs = (uint32_t *)realloc(b->limbs, (size_t)grown * sizeof(uint32_t));
|
|
24
|
+
if (!limbs) {
|
|
25
|
+
fprintf(stderr, "xbintsc: out of memory growing bigint\n");
|
|
26
|
+
abort();
|
|
27
|
+
}
|
|
28
|
+
memset(limbs + b->capacity, 0, (size_t)(grown - b->capacity) * sizeof(uint32_t));
|
|
29
|
+
b->limbs = limbs;
|
|
30
|
+
b->capacity = grown;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Strip leading zero limbs and canonicalise the sign of zero. */
|
|
34
|
+
static void bi_normalize(xt_bigint *b) {
|
|
35
|
+
while (b->length > 0 && b->limbs[b->length - 1] == 0) b->length--;
|
|
36
|
+
if (b->length == 0) b->sign = 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static xt_bigint *bi_zero(void) { return bi_alloc(1); }
|
|
40
|
+
|
|
41
|
+
static xt_bigint *bi_copy(const xt_bigint *src) {
|
|
42
|
+
xt_bigint *r = bi_alloc(src->length ? src->length : 1);
|
|
43
|
+
if (src->length) memcpy(r->limbs, src->limbs, (size_t)src->length * sizeof(uint32_t));
|
|
44
|
+
r->length = src->length;
|
|
45
|
+
r->sign = src->sign;
|
|
46
|
+
return r;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static xt_value bi_wrap(xt_bigint *b) { return XT_FROM_PTR(XT_TAG_BIGINT, b); }
|
|
50
|
+
|
|
51
|
+
#define BI(v) ((xt_bigint *)XT_GET_PTR(v))
|
|
52
|
+
|
|
53
|
+
static void bi_throw_type(const char *message) {
|
|
54
|
+
size_t len = strlen(message);
|
|
55
|
+
char *buffer = (char *)malloc(len + 16);
|
|
56
|
+
snprintf(buffer, len + 16, "TypeError: %s", message);
|
|
57
|
+
xt_throw(xt_string_from_cstr(buffer));
|
|
58
|
+
free(buffer);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static void bi_throw_range(const char *message) {
|
|
62
|
+
size_t len = strlen(message);
|
|
63
|
+
char *buffer = (char *)malloc(len + 16);
|
|
64
|
+
snprintf(buffer, len + 16, "RangeError: %s", message);
|
|
65
|
+
xt_throw(xt_string_from_cstr(buffer));
|
|
66
|
+
free(buffer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static void bi_throw_syntax(const char *message) {
|
|
70
|
+
size_t len = strlen(message);
|
|
71
|
+
char *buffer = (char *)malloc(len + 16);
|
|
72
|
+
snprintf(buffer, len + 16, "SyntaxError: %s", message);
|
|
73
|
+
xt_throw(xt_string_from_cstr(buffer));
|
|
74
|
+
free(buffer);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static xt_bigint *bi_from_u64(int sign, uint64_t magnitude) {
|
|
78
|
+
xt_bigint *r = bi_alloc(2);
|
|
79
|
+
if (magnitude == 0) return r;
|
|
80
|
+
r->limbs[0] = (uint32_t)magnitude;
|
|
81
|
+
r->limbs[1] = (uint32_t)(magnitude >> 32);
|
|
82
|
+
r->length = r->limbs[1] ? 2 : 1;
|
|
83
|
+
r->sign = sign;
|
|
84
|
+
return r;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
xt_value xt_bigint_from_i64(int64_t value) {
|
|
88
|
+
if (value == 0) return bi_wrap(bi_zero());
|
|
89
|
+
uint64_t magnitude = value < 0 ? (uint64_t)(-(value + 1)) + 1 : (uint64_t)value;
|
|
90
|
+
return bi_wrap(bi_from_u64(value < 0 ? -1 : 1, magnitude));
|
|
91
|
+
}
|
|
92
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* -- magnitude helpers ----------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static int bi_cmp_mag(const xt_bigint *a, const xt_bigint *b) {
|
|
4
|
+
if (a->length != b->length) return a->length < b->length ? -1 : 1;
|
|
5
|
+
for (uint32_t i = a->length; i-- > 0;) {
|
|
6
|
+
if (a->limbs[i] != b->limbs[i]) return a->limbs[i] < b->limbs[i] ? -1 : 1;
|
|
7
|
+
}
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static xt_bigint *bi_add_mag(const xt_bigint *a, const xt_bigint *b) {
|
|
12
|
+
uint32_t count = a->length > b->length ? a->length : b->length;
|
|
13
|
+
xt_bigint *r = bi_alloc(count + 1);
|
|
14
|
+
uint64_t carry = 0;
|
|
15
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
16
|
+
uint64_t sum = carry;
|
|
17
|
+
if (i < a->length) sum += a->limbs[i];
|
|
18
|
+
if (i < b->length) sum += b->limbs[i];
|
|
19
|
+
r->limbs[i] = (uint32_t)sum;
|
|
20
|
+
carry = sum >> 32;
|
|
21
|
+
}
|
|
22
|
+
if (carry) r->limbs[count++] = (uint32_t)carry;
|
|
23
|
+
r->length = count;
|
|
24
|
+
r->sign = count ? 1 : 0;
|
|
25
|
+
bi_normalize(r);
|
|
26
|
+
return r;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** `a - b` for magnitudes with `a >= b`. */
|
|
30
|
+
static xt_bigint *bi_sub_mag(const xt_bigint *a, const xt_bigint *b) {
|
|
31
|
+
xt_bigint *r = bi_alloc(a->length);
|
|
32
|
+
int64_t borrow = 0;
|
|
33
|
+
for (uint32_t i = 0; i < a->length; i++) {
|
|
34
|
+
int64_t cur = (int64_t)a->limbs[i] - borrow - (i < b->length ? (int64_t)b->limbs[i] : 0);
|
|
35
|
+
if (cur < 0) {
|
|
36
|
+
cur += 0x100000000LL;
|
|
37
|
+
borrow = 1;
|
|
38
|
+
} else {
|
|
39
|
+
borrow = 0;
|
|
40
|
+
}
|
|
41
|
+
r->limbs[i] = (uint32_t)cur;
|
|
42
|
+
}
|
|
43
|
+
r->length = a->length;
|
|
44
|
+
r->sign = 1;
|
|
45
|
+
bi_normalize(r);
|
|
46
|
+
return r;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static void bi_sub_mag_inplace(xt_bigint *a, const xt_bigint *b) {
|
|
50
|
+
int64_t borrow = 0;
|
|
51
|
+
for (uint32_t i = 0; i < a->length; i++) {
|
|
52
|
+
int64_t cur = (int64_t)a->limbs[i] - borrow - (i < b->length ? (int64_t)b->limbs[i] : 0);
|
|
53
|
+
if (cur < 0) {
|
|
54
|
+
cur += 0x100000000LL;
|
|
55
|
+
borrow = 1;
|
|
56
|
+
} else {
|
|
57
|
+
borrow = 0;
|
|
58
|
+
}
|
|
59
|
+
a->limbs[i] = (uint32_t)cur;
|
|
60
|
+
}
|
|
61
|
+
if (a->sign == 0) a->sign = 1;
|
|
62
|
+
bi_normalize(a);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static xt_bigint *bi_mul_mag(const xt_bigint *a, const xt_bigint *b) {
|
|
66
|
+
if (a->length == 0 || b->length == 0) return bi_zero();
|
|
67
|
+
xt_bigint *r = bi_alloc(a->length + b->length);
|
|
68
|
+
for (uint32_t i = 0; i < a->length; i++) {
|
|
69
|
+
uint64_t carry = 0;
|
|
70
|
+
for (uint32_t j = 0; j < b->length; j++) {
|
|
71
|
+
uint64_t cur = (uint64_t)r->limbs[i + j] + (uint64_t)a->limbs[i] * b->limbs[j] + carry;
|
|
72
|
+
r->limbs[i + j] = (uint32_t)cur;
|
|
73
|
+
carry = cur >> 32;
|
|
74
|
+
}
|
|
75
|
+
uint32_t k = i + b->length;
|
|
76
|
+
while (carry) {
|
|
77
|
+
uint64_t cur = (uint64_t)r->limbs[k] + carry;
|
|
78
|
+
r->limbs[k] = (uint32_t)cur;
|
|
79
|
+
carry = cur >> 32;
|
|
80
|
+
k++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
r->length = a->length + b->length;
|
|
84
|
+
r->sign = 1;
|
|
85
|
+
bi_normalize(r);
|
|
86
|
+
return r;
|
|
87
|
+
}
|
|
88
|
+
|