@grain/stdlib 0.5.12 → 0.6.0
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/CHANGELOG.md +200 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/runtime/bigint.gr
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
@noPervasives
|
|
2
|
+
module Bigint
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
5
|
* Arbitary-precision integers.
|
|
4
6
|
*/
|
|
@@ -13,32 +15,23 @@ The following is the copyright notice from the `nim-lang/bigints` project (MIT L
|
|
|
13
15
|
|
|
14
16
|
Copyright 2019 Dennis Felsing
|
|
15
17
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import WasmF64 from "runtime/unsafe/wasmf64"
|
|
28
|
-
import Exception from "runtime/exception"
|
|
29
|
-
import DS from "runtime/dataStructures"
|
|
30
|
-
import RPrint from "runtime/utils/printing"
|
|
18
|
+
from "runtime/unsafe/memory" include Memory
|
|
19
|
+
from "runtime/unsafe/tags" include Tags
|
|
20
|
+
from "runtime/unsafe/constants" include Constants
|
|
21
|
+
use Constants.{ _UMAX_I64, _SMAX32_I64, _SMAX_I64, _SMAX_I32 }
|
|
22
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
23
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
24
|
+
from "runtime/unsafe/wasmf32" include WasmF32
|
|
25
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
26
|
+
from "runtime/exception" include Exception
|
|
27
|
+
from "runtime/dataStructures" include DataStructures as DS
|
|
28
|
+
from "runtime/utils/printing" include Printing as RPrint
|
|
31
29
|
|
|
32
30
|
// things we need which are missing due to --no-pervasives:
|
|
33
|
-
primitive (!)
|
|
34
|
-
primitive (&&)
|
|
35
|
-
primitive (||)
|
|
36
|
-
primitive throw
|
|
37
|
-
|
|
38
|
-
enum List<a> {
|
|
39
|
-
[],
|
|
40
|
-
[...](a, List<a>),
|
|
41
|
-
}
|
|
31
|
+
primitive (!) = "@not"
|
|
32
|
+
primitive (&&) = "@and"
|
|
33
|
+
primitive (||) = "@or"
|
|
34
|
+
primitive throw = "@throw"
|
|
42
35
|
|
|
43
36
|
// Layout:
|
|
44
37
|
// -------------------------------------------------------
|
|
@@ -70,63 +63,53 @@ let _IS_NEGATIVE = 1n
|
|
|
70
63
|
|
|
71
64
|
@unsafe
|
|
72
65
|
let maxu32 = (a, b) => {
|
|
73
|
-
|
|
66
|
+
use WasmI32.{ ltU as (<) }
|
|
74
67
|
if (a < b) b else a
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
@unsafe
|
|
78
71
|
let minu32 = (a, b) => {
|
|
79
|
-
|
|
72
|
+
use WasmI32.{ ltU as (<) }
|
|
80
73
|
if (a < b) a else b
|
|
81
74
|
}
|
|
82
75
|
|
|
83
76
|
@unsafe
|
|
84
77
|
let minu64 = (a, b) => {
|
|
85
|
-
|
|
78
|
+
use WasmI32.{ ltU as (<) }
|
|
86
79
|
if (a < b) a else b
|
|
87
80
|
}
|
|
88
81
|
|
|
89
|
-
// TODO(#1188): use faster abs algos
|
|
90
|
-
// https://stackoverflow.com/questions/664852/which-is-the-fastest-way-to-get-the-absolute-value-of-a-number
|
|
91
|
-
|
|
92
82
|
@unsafe
|
|
93
83
|
let absi32 = n => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
n
|
|
99
|
-
}
|
|
84
|
+
use WasmI32.{ (>>), (^), (-) }
|
|
85
|
+
let temp = n >> 31n
|
|
86
|
+
let n = n ^ temp
|
|
87
|
+
n - temp
|
|
100
88
|
}
|
|
101
89
|
|
|
102
90
|
@unsafe
|
|
103
91
|
let absi64 = n => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
n
|
|
109
|
-
}
|
|
92
|
+
use WasmI64.{ (>>), (^), (-) }
|
|
93
|
+
let temp = n >> 63N
|
|
94
|
+
let n = n ^ temp
|
|
95
|
+
n - temp
|
|
110
96
|
}
|
|
111
97
|
|
|
112
98
|
@unsafe
|
|
113
99
|
let lnot = n => {
|
|
114
|
-
WasmI32.
|
|
100
|
+
use WasmI32.{ (^) }
|
|
101
|
+
n ^ -1n
|
|
115
102
|
}
|
|
116
103
|
|
|
117
104
|
@unsafe
|
|
118
105
|
let init = (limbs: WasmI32) => {
|
|
119
|
-
|
|
120
|
-
let (*) = WasmI32.mul
|
|
121
|
-
let (<) = WasmI32.ltS
|
|
122
|
-
let (==) = WasmI32.eq
|
|
123
|
-
let (&) = WasmI32.and
|
|
106
|
+
use WasmI32.{ (+), (*), (<), (==), (&) }
|
|
124
107
|
if (!WasmI32.eqz(limbs & 0x80000000n)) {
|
|
125
108
|
// MSB is 1. We reject these sizes because they will cause overflows
|
|
126
109
|
// in our multiplication/division algorithms. This means that BigInts
|
|
127
110
|
// are limited to 16+17179869176 bytes, or just over 16GiB.
|
|
128
111
|
throw Exception.InvalidArgument(
|
|
129
|
-
"Cannot allocate BigInt with >= 2147483648 limbs"
|
|
112
|
+
"Cannot allocate BigInt with >= 2147483648 limbs",
|
|
130
113
|
)
|
|
131
114
|
}
|
|
132
115
|
|
|
@@ -150,11 +133,12 @@ let init = (limbs: WasmI32) => {
|
|
|
150
133
|
|
|
151
134
|
// For debugging
|
|
152
135
|
@unsafe
|
|
153
|
-
|
|
136
|
+
provide let debugDumpNumber = (num: WasmI32) => {
|
|
137
|
+
use WasmI32.{ (*), (+), (-), (&), (>>>), (<) }
|
|
154
138
|
//let num = WasmI32.fromGrain(num)
|
|
155
139
|
RPrint.printString("-=-=-=-== debug dump ==-=-=-=-")
|
|
156
140
|
RPrint.printString("Ref Count:")
|
|
157
|
-
RPrint.printNumber(WasmI64.extendI32U(WasmI32.load(
|
|
141
|
+
RPrint.printNumber(WasmI64.extendI32U(WasmI32.load(num - 8n, 0n)))
|
|
158
142
|
RPrint.printString("Heap Tag:")
|
|
159
143
|
RPrint.printNumber(WasmI64.extendI32U(WasmI32.load(num, 0n)))
|
|
160
144
|
RPrint.printString("Boxed Num Tag:")
|
|
@@ -163,26 +147,20 @@ export let debugDumpNumber = (num: WasmI32) => {
|
|
|
163
147
|
let limbs = WasmI32.load(num, 8n)
|
|
164
148
|
RPrint.printNumber(WasmI64.extendI32U(limbs))
|
|
165
149
|
RPrint.printString("Flags:")
|
|
166
|
-
RPrint.printNumber(
|
|
167
|
-
WasmI64.extendI32U(WasmI32.and(0xffffn, WasmI32.load(num, 12n)))
|
|
168
|
-
)
|
|
150
|
+
RPrint.printNumber(WasmI64.extendI32U(0xffffn & WasmI32.load(num, 12n)))
|
|
169
151
|
RPrint.printString("<reserved>:")
|
|
170
152
|
RPrint.printNumber(
|
|
171
|
-
WasmI64.extendI32U(
|
|
172
|
-
WasmI32.shrU(WasmI32.and(0xffff0000n, WasmI32.load(num, 12n)), 16n)
|
|
173
|
-
)
|
|
153
|
+
WasmI64.extendI32U((0xffff0000n & WasmI32.load(num, 12n)) >>> 16n)
|
|
174
154
|
)
|
|
175
155
|
RPrint.printString("Limbs:")
|
|
176
|
-
for (let mut i = 0n;
|
|
156
|
+
for (let mut i = 0n; i < limbs; i += 1n) {
|
|
177
157
|
// if a nonzero limb is found, then we're at the min
|
|
178
|
-
let (*) = WasmI32.mul
|
|
179
|
-
let (+) = WasmI32.add
|
|
180
158
|
RPrint.printNumber(WasmI64.load(num, (i + 2n) * 8n))
|
|
181
159
|
}
|
|
182
160
|
}
|
|
183
161
|
|
|
184
162
|
@unsafe
|
|
185
|
-
|
|
163
|
+
provide let getSize = ptr => {
|
|
186
164
|
WasmI32.load(ptr, 8n)
|
|
187
165
|
}
|
|
188
166
|
|
|
@@ -192,32 +170,30 @@ let setSize = (ptr, n) => {
|
|
|
192
170
|
}
|
|
193
171
|
|
|
194
172
|
@unsafe
|
|
195
|
-
|
|
173
|
+
provide let getFlags = ptr => {
|
|
196
174
|
WasmI32.load(ptr, 12n)
|
|
197
175
|
}
|
|
198
176
|
|
|
199
177
|
@unsafe
|
|
200
178
|
let flagIsSet = (ptr, flag) => {
|
|
201
|
-
WasmI32.
|
|
179
|
+
use WasmI32.{ (&), (!=) }
|
|
180
|
+
(getFlags(ptr) & flag) != 0n
|
|
202
181
|
}
|
|
203
182
|
|
|
204
183
|
@unsafe
|
|
205
184
|
let getFlag = (ptr, flag) => {
|
|
185
|
+
use WasmI32.{ (&), (>>>) }
|
|
206
186
|
let setFlags = WasmI32.load(ptr, 12n)
|
|
207
|
-
|
|
187
|
+
(setFlags & flag) >>> WasmI32.ctz(flag)
|
|
208
188
|
}
|
|
209
189
|
|
|
210
190
|
@unsafe
|
|
211
191
|
let setFlag = (ptr, flag, value) => {
|
|
212
|
-
|
|
213
|
-
let (|) = WasmI32.or
|
|
214
|
-
let (&) = WasmI32.and
|
|
192
|
+
use WasmI32.{ (*), (|), (&) }
|
|
215
193
|
let (!) = lnot
|
|
216
194
|
WasmI32.store(
|
|
217
195
|
ptr,
|
|
218
|
-
WasmI32.load(ptr, 12n) & !flag |
|
|
219
|
-
flag *
|
|
220
|
-
(if (WasmI32.eqz(value)) {
|
|
196
|
+
WasmI32.load(ptr, 12n) & !flag | flag * (if (WasmI32.eqz(value)) {
|
|
221
197
|
0n
|
|
222
198
|
} else {
|
|
223
199
|
1n
|
|
@@ -227,16 +203,14 @@ let setFlag = (ptr, flag, value) => {
|
|
|
227
203
|
}
|
|
228
204
|
|
|
229
205
|
@unsafe
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
let (+) = WasmI32.add
|
|
206
|
+
provide let getLimb = (ptr, i) => {
|
|
207
|
+
use WasmI32.{ (+), (*) }
|
|
233
208
|
WasmI64.load(ptr, (i + 2n) * 8n)
|
|
234
209
|
}
|
|
235
210
|
|
|
236
211
|
@unsafe
|
|
237
212
|
let setLimb = (ptr, i, v) => {
|
|
238
|
-
|
|
239
|
-
let (+) = WasmI32.add
|
|
213
|
+
use WasmI32.{ (+), (*) }
|
|
240
214
|
WasmI64.store(ptr, v, (i + 2n) * 8n)
|
|
241
215
|
}
|
|
242
216
|
|
|
@@ -245,12 +219,11 @@ let getHalfSize = ptr => {
|
|
|
245
219
|
// for when it's important to know *precisely* the number of half-limbs,
|
|
246
220
|
// excluding trailing zeros
|
|
247
221
|
let size = getSize(ptr)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
let (-) = WasmI32.sub
|
|
222
|
+
use WasmI32.{ (-), (<<), gtU as (>) }
|
|
223
|
+
use WasmI64.{ (>>>) }
|
|
251
224
|
if (
|
|
252
225
|
size > 0n &&
|
|
253
|
-
WasmI32.eqz(WasmI32.wrapI64(
|
|
226
|
+
WasmI32.eqz(WasmI32.wrapI64(getLimb(ptr, size - 1n) >>> 32N))
|
|
254
227
|
) {
|
|
255
228
|
// last half-limb is trailing zeros
|
|
256
229
|
(size << 1n) - 1n
|
|
@@ -264,22 +237,19 @@ let getHalfSize = ptr => {
|
|
|
264
237
|
// using 32-bit than with 64-bit)
|
|
265
238
|
@unsafe
|
|
266
239
|
let getHalfLimb = (ptr, i) => {
|
|
267
|
-
|
|
268
|
-
let (+) = WasmI32.add
|
|
240
|
+
use WasmI32.{ (+), (*) }
|
|
269
241
|
WasmI32.load(ptr, (i + 4n) * 4n)
|
|
270
242
|
}
|
|
271
243
|
|
|
272
244
|
@unsafe
|
|
273
245
|
let setHalfLimb = (ptr, i, v) => {
|
|
274
|
-
|
|
275
|
-
let (+) = WasmI32.add
|
|
246
|
+
use WasmI32.{ (+), (*) }
|
|
276
247
|
WasmI32.store(ptr, v, (i + 4n) * 4n)
|
|
277
248
|
}
|
|
278
249
|
|
|
279
250
|
@unsafe
|
|
280
251
|
let clone = (num: WasmI32) => {
|
|
281
|
-
|
|
282
|
-
let (*) = WasmI32.mul
|
|
252
|
+
use WasmI32.{ (+), (*) }
|
|
283
253
|
let len = getSize(num) * 8n + 16n
|
|
284
254
|
let ret = Memory.malloc(len)
|
|
285
255
|
Memory.copy(ret, num, len)
|
|
@@ -288,8 +258,7 @@ let clone = (num: WasmI32) => {
|
|
|
288
258
|
|
|
289
259
|
@unsafe
|
|
290
260
|
let cloneWithLen = (num: WasmI32, len: WasmI32) => {
|
|
291
|
-
|
|
292
|
-
let (*) = WasmI32.mul
|
|
261
|
+
use WasmI32.{ (+), (*) }
|
|
293
262
|
let oldlen = getSize(num) * 8n + 16n
|
|
294
263
|
let newlen = len * 8n + 16n
|
|
295
264
|
let ret = Memory.malloc(newlen)
|
|
@@ -307,10 +276,8 @@ let cloneWithLen = (num: WasmI32, len: WasmI32) => {
|
|
|
307
276
|
let trimNumberInPlace = (num: WasmI32) => {
|
|
308
277
|
let numLimbs = getSize(num)
|
|
309
278
|
let mut neededLimbs = numLimbs
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
let (-) = WasmI32.sub
|
|
313
|
-
let (>=) = WasmI32.geS
|
|
279
|
+
use WasmI64.{ (!=) }
|
|
280
|
+
use WasmI32.{ (-), (>=), (==) }
|
|
314
281
|
for (let mut i = numLimbs - 1n; i >= 0n; i -= 1n) {
|
|
315
282
|
// if a nonzero limb is found, then we're at the min
|
|
316
283
|
if (getLimb(num, i) != 0N) {
|
|
@@ -337,13 +304,14 @@ let makeZero = () => {
|
|
|
337
304
|
}
|
|
338
305
|
|
|
339
306
|
@unsafe
|
|
340
|
-
|
|
307
|
+
provide let makeWrappedInt32 = (value: WasmI32) => {
|
|
308
|
+
use WasmI32.{ (*), (<) }
|
|
341
309
|
let ret = init(1n)
|
|
342
|
-
if (
|
|
310
|
+
if (value < 0n) {
|
|
343
311
|
setFlag(ret, _IS_NEGATIVE, 1n)
|
|
344
312
|
}
|
|
345
|
-
let value = if (
|
|
346
|
-
|
|
313
|
+
let value = if (value < 0n) {
|
|
314
|
+
value * -1n
|
|
347
315
|
} else {
|
|
348
316
|
value
|
|
349
317
|
}
|
|
@@ -352,20 +320,21 @@ export let makeWrappedInt32 = (value: WasmI32) => {
|
|
|
352
320
|
}
|
|
353
321
|
|
|
354
322
|
@unsafe
|
|
355
|
-
|
|
323
|
+
provide let makeWrappedUint32 = (value: WasmI32) => {
|
|
356
324
|
let ret = init(1n)
|
|
357
325
|
setLimb(ret, 0n, WasmI64.extendI32U(value))
|
|
358
326
|
ret
|
|
359
327
|
}
|
|
360
328
|
|
|
361
329
|
@unsafe
|
|
362
|
-
|
|
330
|
+
provide let makeWrappedInt64 = (value: WasmI64) => {
|
|
331
|
+
use WasmI64.{ (*), (<) }
|
|
363
332
|
let ret = init(1n)
|
|
364
|
-
if (
|
|
333
|
+
if (value < 0N) {
|
|
365
334
|
setFlag(ret, _IS_NEGATIVE, 1n)
|
|
366
335
|
}
|
|
367
|
-
let value = if (
|
|
368
|
-
|
|
336
|
+
let value = if (value < 0N) {
|
|
337
|
+
value * -1N
|
|
369
338
|
} else {
|
|
370
339
|
value
|
|
371
340
|
}
|
|
@@ -374,14 +343,14 @@ export let makeWrappedInt64 = (value: WasmI64) => {
|
|
|
374
343
|
}
|
|
375
344
|
|
|
376
345
|
@unsafe
|
|
377
|
-
|
|
346
|
+
provide let makeWrappedUint64 = (value: WasmI64) => {
|
|
378
347
|
let ret = init(1n)
|
|
379
348
|
setLimb(ret, 0n, value)
|
|
380
349
|
ret
|
|
381
350
|
}
|
|
382
351
|
|
|
383
352
|
@unsafe
|
|
384
|
-
|
|
353
|
+
provide let isNegative = (num: WasmI32) => {
|
|
385
354
|
flagIsSet(num, _IS_NEGATIVE)
|
|
386
355
|
}
|
|
387
356
|
|
|
@@ -389,19 +358,16 @@ export let isNegative = (num: WasmI32) => {
|
|
|
389
358
|
* Returns true if the given bigint is equal to zero
|
|
390
359
|
*/
|
|
391
360
|
@unsafe
|
|
392
|
-
|
|
361
|
+
provide let eqz = (num: WasmI32) => {
|
|
393
362
|
let numLimbs = getSize(num)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
let (>=) = WasmI32.geS
|
|
397
|
-
let mut result = 1n
|
|
363
|
+
use WasmI64.{ (!=) }
|
|
364
|
+
use WasmI32.{ (-), (>=) }
|
|
398
365
|
for (let mut i = numLimbs - 1n; i >= 0n; i -= 1n) {
|
|
399
366
|
if (getLimb(num, i) != 0N) {
|
|
400
|
-
|
|
401
|
-
break
|
|
367
|
+
return false
|
|
402
368
|
}
|
|
403
369
|
}
|
|
404
|
-
|
|
370
|
+
return true
|
|
405
371
|
}
|
|
406
372
|
|
|
407
373
|
@unsafe
|
|
@@ -411,7 +377,7 @@ let negateInPlace = (num: WasmI32) => {
|
|
|
411
377
|
}
|
|
412
378
|
|
|
413
379
|
@unsafe
|
|
414
|
-
|
|
380
|
+
provide let negate = (num: WasmI32) => {
|
|
415
381
|
let ret = clone(num)
|
|
416
382
|
setFlag(ret, _IS_NEGATIVE, if (flagIsSet(ret, _IS_NEGATIVE)) 0n else 1n)
|
|
417
383
|
ret
|
|
@@ -424,7 +390,7 @@ let absInPlace = (num: WasmI32) => {
|
|
|
424
390
|
}
|
|
425
391
|
|
|
426
392
|
@unsafe
|
|
427
|
-
|
|
393
|
+
provide let abs = (num: WasmI32) => {
|
|
428
394
|
let ret = clone(num)
|
|
429
395
|
setFlag(ret, _IS_NEGATIVE, 0n)
|
|
430
396
|
ret
|
|
@@ -434,9 +400,9 @@ export let abs = (num: WasmI32) => {
|
|
|
434
400
|
* Conversions
|
|
435
401
|
*/
|
|
436
402
|
@unsafe
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
403
|
+
provide let canConvertToInt32 = (num: WasmI32) => {
|
|
404
|
+
use WasmI64.{ leU as (<=) }
|
|
405
|
+
use WasmI32.{ (==) }
|
|
440
406
|
let numLimbs = getSize(num)
|
|
441
407
|
if (numLimbs == 0n) {
|
|
442
408
|
true
|
|
@@ -449,9 +415,9 @@ export let canConvertToInt32 = (num: WasmI32) => {
|
|
|
449
415
|
}
|
|
450
416
|
|
|
451
417
|
@unsafe
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
418
|
+
provide let toInt32 = (num: WasmI32) => {
|
|
419
|
+
use WasmI64.{ leU as (<=) }
|
|
420
|
+
use WasmI32.{ (==), (*) }
|
|
455
421
|
let numLimbs = getSize(num)
|
|
456
422
|
if (numLimbs == 0n) {
|
|
457
423
|
0n
|
|
@@ -459,7 +425,7 @@ export let toInt32 = (num: WasmI32) => {
|
|
|
459
425
|
let limb = getLimb(num, 0n)
|
|
460
426
|
if (limb <= _SMAX32_I64) {
|
|
461
427
|
if (flagIsSet(num, _IS_NEGATIVE)) {
|
|
462
|
-
|
|
428
|
+
-1n * WasmI32.wrapI64(limb)
|
|
463
429
|
} else {
|
|
464
430
|
WasmI32.wrapI64(limb)
|
|
465
431
|
}
|
|
@@ -472,9 +438,9 @@ export let toInt32 = (num: WasmI32) => {
|
|
|
472
438
|
}
|
|
473
439
|
|
|
474
440
|
@unsafe
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
441
|
+
provide let canConvertToInt64 = (num: WasmI32) => {
|
|
442
|
+
use WasmI64.{ leU as (<=) }
|
|
443
|
+
use WasmI32.{ (==) }
|
|
478
444
|
let numLimbs = getSize(num)
|
|
479
445
|
if (numLimbs == 0n) {
|
|
480
446
|
true
|
|
@@ -491,9 +457,9 @@ export let canConvertToInt64 = (num: WasmI32) => {
|
|
|
491
457
|
}
|
|
492
458
|
|
|
493
459
|
@unsafe
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
460
|
+
provide let toInt64 = (num: WasmI32) => {
|
|
461
|
+
use WasmI64.{ leU as (<=), (*) }
|
|
462
|
+
use WasmI32.{ (==) }
|
|
497
463
|
let numLimbs = getSize(num)
|
|
498
464
|
if (numLimbs == 0n) {
|
|
499
465
|
0N
|
|
@@ -501,7 +467,7 @@ export let toInt64 = (num: WasmI32) => {
|
|
|
501
467
|
let limb = getLimb(num, 0n)
|
|
502
468
|
if (limb <= _SMAX32_I64) {
|
|
503
469
|
if (flagIsSet(num, _IS_NEGATIVE)) {
|
|
504
|
-
|
|
470
|
+
-1N * limb
|
|
505
471
|
} else {
|
|
506
472
|
limb
|
|
507
473
|
}
|
|
@@ -514,13 +480,27 @@ export let toInt64 = (num: WasmI32) => {
|
|
|
514
480
|
}
|
|
515
481
|
|
|
516
482
|
@unsafe
|
|
517
|
-
|
|
483
|
+
provide let toUnsignedInt64 = (num: WasmI32) => {
|
|
484
|
+
use WasmI64.{ leU as (<=) }
|
|
485
|
+
use WasmI32.{ (==) }
|
|
486
|
+
let numLimbs = getSize(num)
|
|
487
|
+
if (numLimbs == 0n) {
|
|
488
|
+
0N
|
|
489
|
+
} else if (numLimbs == 1n) {
|
|
490
|
+
let limb = getLimb(num, 0n)
|
|
491
|
+
limb
|
|
492
|
+
} else {
|
|
493
|
+
throw Exception.Overflow
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
@unsafe
|
|
498
|
+
provide let toFloat64 = (num: WasmI32) => {
|
|
518
499
|
// approximate!
|
|
519
500
|
// semi-port of https://github.com/JuliaLang/julia/issues/31293#issuecomment-477220553
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
let (*) = WasmF64.mul
|
|
501
|
+
use WasmI64.{ leU as (<=) }
|
|
502
|
+
use WasmI32.{ (==) }
|
|
503
|
+
use WasmF64.{ (+), (*) }
|
|
524
504
|
let numLimbs = getSize(num)
|
|
525
505
|
let res = if (eqz(num)) {
|
|
526
506
|
0.0W
|
|
@@ -538,11 +518,13 @@ export let toFloat64 = (num: WasmI32) => {
|
|
|
538
518
|
let factor = WasmF64.reinterpretI64(
|
|
539
519
|
0b0100001111110000000000000000000000000000000000000000000000000000N
|
|
540
520
|
)
|
|
541
|
-
let mut result = 0.
|
|
542
|
-
|
|
521
|
+
let mut result = 0.0W
|
|
522
|
+
use WasmI32.{ (+) }
|
|
523
|
+
for (let mut i = 0n; WasmI32.ltU(i, numLimbs); i += 1n) {
|
|
543
524
|
if (!WasmI32.eqz(i)) {
|
|
544
525
|
result *= factor
|
|
545
526
|
}
|
|
527
|
+
use WasmF64.{ (+) }
|
|
546
528
|
result += WasmF64.convertI64U(getLimb(num, i))
|
|
547
529
|
}
|
|
548
530
|
result
|
|
@@ -555,7 +537,7 @@ export let toFloat64 = (num: WasmI32) => {
|
|
|
555
537
|
}
|
|
556
538
|
|
|
557
539
|
@unsafe
|
|
558
|
-
|
|
540
|
+
provide let toFloat32 = (num: WasmI32) => {
|
|
559
541
|
WasmF32.demoteF64(toFloat64(num))
|
|
560
542
|
}
|
|
561
543
|
|
|
@@ -565,52 +547,66 @@ export let toFloat32 = (num: WasmI32) => {
|
|
|
565
547
|
|
|
566
548
|
@unsafe
|
|
567
549
|
let cmpUnsignedI64 = (num1: WasmI32, num2: WasmI64) => {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
let (!=) = WasmI32.ne
|
|
571
|
-
let (>=) = WasmI32.geS
|
|
550
|
+
use WasmI32.{ (-), (>=), (==), (!=) }
|
|
551
|
+
use WasmI64.{ (*), (<) }
|
|
572
552
|
let num1Limbs = getSize(num1)
|
|
573
553
|
let num2Limbs = 1n
|
|
574
554
|
let delta = num1Limbs - num2Limbs
|
|
575
|
-
let num2abs = if (
|
|
555
|
+
let num2abs = if (num2 < 0N) -1N * num2 else num2
|
|
576
556
|
if (delta != 0n) {
|
|
577
|
-
delta
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
} else if (WasmI64.ltU(limb2, limb1)) {
|
|
588
|
-
result = 1n
|
|
589
|
-
break
|
|
590
|
-
}
|
|
557
|
+
return delta
|
|
558
|
+
}
|
|
559
|
+
// num1 and num2 have the same size. Compare all limbs, high to low
|
|
560
|
+
for (let mut i = num1Limbs - 1n; i >= 0n; i -= 1n) {
|
|
561
|
+
let limb1 = getLimb(num1, i)
|
|
562
|
+
let limb2 = if (i == 0n) num2abs else 0N
|
|
563
|
+
if (WasmI64.ltU(limb1, limb2)) {
|
|
564
|
+
return -1n
|
|
565
|
+
} else if (WasmI64.ltU(limb2, limb1)) {
|
|
566
|
+
return 1n
|
|
591
567
|
}
|
|
592
|
-
result
|
|
593
568
|
}
|
|
569
|
+
|
|
570
|
+
return 0n
|
|
594
571
|
}
|
|
595
572
|
|
|
596
573
|
@unsafe
|
|
597
|
-
|
|
574
|
+
provide let cmpI64 = (num1: WasmI32, num2: WasmI64) => {
|
|
575
|
+
use WasmI64.{ (<) }
|
|
576
|
+
use WasmI32.{ (*) }
|
|
598
577
|
if (eqz(num1)) {
|
|
599
578
|
if (WasmI64.eqz(num2)) {
|
|
600
579
|
0n
|
|
601
|
-
} else if (
|
|
580
|
+
} else if (num2 < 0N) {
|
|
602
581
|
1n
|
|
603
582
|
} else {
|
|
604
583
|
-1n
|
|
605
584
|
}
|
|
606
585
|
} else if (flagIsSet(num1, _IS_NEGATIVE)) {
|
|
607
|
-
if (WasmI64.eqz(num2) || !
|
|
586
|
+
if (WasmI64.eqz(num2) || !(num2 < 0N)) {
|
|
608
587
|
-1n
|
|
609
588
|
} else {
|
|
610
|
-
|
|
589
|
+
-1n * cmpUnsignedI64(num1, num2)
|
|
590
|
+
}
|
|
591
|
+
} else {
|
|
592
|
+
if (WasmI64.eqz(num2) || num2 < 0N) {
|
|
593
|
+
1n
|
|
594
|
+
} else {
|
|
595
|
+
cmpUnsignedI64(num1, num2)
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
@unsafe
|
|
601
|
+
provide let cmpU64 = (num1: WasmI32, num2: WasmI64) => {
|
|
602
|
+
if (eqz(num1)) {
|
|
603
|
+
if (WasmI64.eqz(num2)) {
|
|
604
|
+
0n
|
|
605
|
+
} else {
|
|
606
|
+
1n
|
|
611
607
|
}
|
|
612
608
|
} else {
|
|
613
|
-
if (WasmI64.eqz(num2)
|
|
609
|
+
if (WasmI64.eqz(num2)) {
|
|
614
610
|
1n
|
|
615
611
|
} else {
|
|
616
612
|
cmpUnsignedI64(num1, num2)
|
|
@@ -619,10 +615,9 @@ export let cmpI64 = (num1: WasmI32, num2: WasmI64) => {
|
|
|
619
615
|
}
|
|
620
616
|
|
|
621
617
|
@unsafe
|
|
622
|
-
|
|
618
|
+
provide let cmpF64 = (num1: WasmI32, num2: WasmF64) => {
|
|
623
619
|
let asf64 = toFloat64(num1)
|
|
624
|
-
|
|
625
|
-
let (>) = WasmF64.gt
|
|
620
|
+
use WasmF64.{ (<), (>) }
|
|
626
621
|
if (asf64 < num2) {
|
|
627
622
|
-1n
|
|
628
623
|
} else if (asf64 > num2) {
|
|
@@ -633,40 +628,34 @@ export let cmpF64 = (num1: WasmI32, num2: WasmF64) => {
|
|
|
633
628
|
}
|
|
634
629
|
|
|
635
630
|
@unsafe
|
|
636
|
-
|
|
631
|
+
provide let cmpF32 = (num1: WasmI32, num2: WasmF32) => {
|
|
637
632
|
cmpF64(num1, WasmF64.promoteF32(num2))
|
|
638
633
|
}
|
|
639
634
|
|
|
640
635
|
@unsafe
|
|
641
636
|
let cmpUnsigned = (num1: WasmI32, num2: WasmI32) => {
|
|
642
|
-
|
|
643
|
-
let (!=) = WasmI32.ne
|
|
644
|
-
let (>=) = WasmI32.geS
|
|
637
|
+
use WasmI32.{ (-), (>=), (!=) }
|
|
645
638
|
let num1Limbs = getSize(num1)
|
|
646
639
|
let num2Limbs = getSize(num2)
|
|
647
640
|
let delta = num1Limbs - num2Limbs
|
|
648
641
|
if (delta != 0n) {
|
|
649
|
-
delta
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
} else if (WasmI64.ltU(limb2, limb1)) {
|
|
660
|
-
result = 1n
|
|
661
|
-
break
|
|
662
|
-
}
|
|
642
|
+
return delta
|
|
643
|
+
}
|
|
644
|
+
// num1 and num2 have the same size. Compare all limbs, high to low
|
|
645
|
+
for (let mut i = num1Limbs - 1n; i >= 0n; i -= 1n) {
|
|
646
|
+
let limb1 = getLimb(num1, i)
|
|
647
|
+
let limb2 = getLimb(num2, i)
|
|
648
|
+
if (WasmI64.ltU(limb1, limb2)) {
|
|
649
|
+
return -1n
|
|
650
|
+
} else if (WasmI64.ltU(limb2, limb1)) {
|
|
651
|
+
return 1n
|
|
663
652
|
}
|
|
664
|
-
result
|
|
665
653
|
}
|
|
654
|
+
return 0n
|
|
666
655
|
}
|
|
667
656
|
|
|
668
657
|
@unsafe
|
|
669
|
-
|
|
658
|
+
provide let cmp = (num1: WasmI32, num2: WasmI32) => {
|
|
670
659
|
if (eqz(num1)) {
|
|
671
660
|
if (eqz(num2)) {
|
|
672
661
|
0n
|
|
@@ -691,33 +680,39 @@ export let cmp = (num1: WasmI32, num2: WasmI32) => {
|
|
|
691
680
|
}
|
|
692
681
|
|
|
693
682
|
@unsafe
|
|
694
|
-
|
|
695
|
-
WasmI32.
|
|
683
|
+
provide let eq = (num1: WasmI32, num2: WasmI32) => {
|
|
684
|
+
use WasmI32.{ (==) }
|
|
685
|
+
cmp(num1, num2) == 0n
|
|
696
686
|
}
|
|
697
687
|
|
|
698
688
|
@unsafe
|
|
699
|
-
|
|
700
|
-
WasmI32.
|
|
689
|
+
provide let ne = (num1: WasmI32, num2: WasmI32) => {
|
|
690
|
+
use WasmI32.{ (!=) }
|
|
691
|
+
cmp(num1, num2) != 0n
|
|
701
692
|
}
|
|
702
693
|
|
|
703
694
|
@unsafe
|
|
704
|
-
|
|
705
|
-
WasmI32.
|
|
695
|
+
provide let lt = (num1: WasmI32, num2: WasmI32) => {
|
|
696
|
+
use WasmI32.{ (<) }
|
|
697
|
+
cmp(num1, num2) < 0n
|
|
706
698
|
}
|
|
707
699
|
|
|
708
700
|
@unsafe
|
|
709
|
-
|
|
710
|
-
WasmI32.
|
|
701
|
+
provide let lte = (num1: WasmI32, num2: WasmI32) => {
|
|
702
|
+
use WasmI32.{ (<=) }
|
|
703
|
+
cmp(num1, num2) <= 0n
|
|
711
704
|
}
|
|
712
705
|
|
|
713
706
|
@unsafe
|
|
714
|
-
|
|
715
|
-
WasmI32.
|
|
707
|
+
provide let gt = (num1: WasmI32, num2: WasmI32) => {
|
|
708
|
+
use WasmI32.{ (>) }
|
|
709
|
+
cmp(num1, num2) > 0n
|
|
716
710
|
}
|
|
717
711
|
|
|
718
712
|
@unsafe
|
|
719
|
-
|
|
720
|
-
WasmI32.
|
|
713
|
+
provide let gte = (num1: WasmI32, num2: WasmI32) => {
|
|
714
|
+
use WasmI32.{ (>=) }
|
|
715
|
+
cmp(num1, num2) >= 0n
|
|
721
716
|
}
|
|
722
717
|
|
|
723
718
|
/*
|
|
@@ -727,9 +722,8 @@ export let gte = (num1: WasmI32, num2: WasmI32) => {
|
|
|
727
722
|
@unsafe
|
|
728
723
|
let countTrailingZeroBits = (num: WasmI32) => {
|
|
729
724
|
let numLimbs = getSize(num)
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
let (<) = WasmI32.ltS
|
|
725
|
+
use WasmI64.{ (!=) }
|
|
726
|
+
use WasmI32.{ (+), (<) }
|
|
733
727
|
let mut result = 0n
|
|
734
728
|
for (let mut i = 0n; i < numLimbs; i += 1n) {
|
|
735
729
|
let limb = getLimb(num, i)
|
|
@@ -786,49 +780,46 @@ let _SIZES = [>
|
|
|
786
780
|
]
|
|
787
781
|
|
|
788
782
|
@unsafe
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
if (
|
|
783
|
+
provide let bigIntToString = (num: WasmI32, base: WasmI32) => {
|
|
784
|
+
use WasmI32.{ (+), (<), (>) }
|
|
785
|
+
let getDigit = n => WasmI32.load8U(WasmI32.fromGrain(_DIGITS) + n, 8n)
|
|
786
|
+
if (base < 2n || base > 32n) {
|
|
793
787
|
throw Exception.InvalidArgument("toString base must be in range [2,32]")
|
|
794
788
|
}
|
|
789
|
+
use WasmI64.{ (-), (*), (|), (<<), (>) }
|
|
795
790
|
if (eqz(num)) {
|
|
796
791
|
"0"
|
|
797
792
|
} else {
|
|
798
793
|
let size = DS.untagSimpleNumber(_SIZES[DS.tagSimpleNumber(base)])
|
|
799
|
-
|
|
794
|
+
use WasmI32.{ (==), (-) as subWasmI32 }
|
|
800
795
|
let mut result = []
|
|
801
796
|
if (base == 2n || base == 4n || base == 8n || base == 16n || base == 32n) {
|
|
802
797
|
// if base is a power of two, use optimized path
|
|
803
798
|
let bits = WasmI64.extendI32U(WasmI32.ctz(base))
|
|
804
|
-
let mask =
|
|
799
|
+
let mask = (1N << bits) - 1N
|
|
805
800
|
let numLimbs = getSize(num)
|
|
806
|
-
let totalBits = WasmI64.
|
|
807
|
-
WasmI64.
|
|
808
|
-
WasmI64.clz(getLimb(num, WasmI32.sub(numLimbs, 1n)))
|
|
809
|
-
)
|
|
801
|
+
let totalBits = 64N * WasmI64.extendI32U(numLimbs) -
|
|
802
|
+
WasmI64.clz(getLimb(num, subWasmI32(numLimbs, 1n)))
|
|
810
803
|
let mut acc = 0N
|
|
811
804
|
let mut accBits = 0N
|
|
812
|
-
for (let mut i = 0n;
|
|
805
|
+
for (let mut i = 0n; i < numLimbs; i += 1n) {
|
|
806
|
+
use WasmI64.{ (+), (&), (>>>), (>=) }
|
|
813
807
|
let limb = getLimb(num, i)
|
|
814
|
-
acc =
|
|
815
|
-
accBits
|
|
816
|
-
while (
|
|
808
|
+
acc = acc | limb << accBits
|
|
809
|
+
accBits += 64N
|
|
810
|
+
while (accBits >= bits) {
|
|
817
811
|
result = [
|
|
818
|
-
DS.tagChar(getDigit(WasmI32.wrapI64(
|
|
812
|
+
DS.tagChar(getDigit(WasmI32.wrapI64(acc & mask))),
|
|
819
813
|
...result
|
|
820
814
|
]
|
|
821
|
-
acc =
|
|
822
|
-
if (
|
|
823
|
-
acc =
|
|
824
|
-
limb,
|
|
825
|
-
WasmI64.sub(64N, WasmI64.sub(accBits, bits))
|
|
826
|
-
)
|
|
815
|
+
acc = acc >>> bits
|
|
816
|
+
if (accBits > 64N) {
|
|
817
|
+
acc = limb >>> (64N - (accBits - bits))
|
|
827
818
|
}
|
|
828
|
-
accBits
|
|
819
|
+
accBits -= bits
|
|
829
820
|
}
|
|
830
821
|
}
|
|
831
|
-
if (
|
|
822
|
+
if (acc > 0N) {
|
|
832
823
|
result = [DS.tagChar(getDigit(WasmI32.wrapI64(acc))), ...result]
|
|
833
824
|
}
|
|
834
825
|
} else {
|
|
@@ -837,21 +828,19 @@ export let bigIntToString = (num: WasmI32, base: WasmI32) => {
|
|
|
837
828
|
let mut tmp = clone(num)
|
|
838
829
|
setFlag(tmp, _IS_NEGATIVE, 0n)
|
|
839
830
|
while (!eqz(tmp)) {
|
|
840
|
-
|
|
841
|
-
let (<<) = WasmI32.shl
|
|
831
|
+
use WasmI32.{ (-), (<<), (>=) }
|
|
842
832
|
let tmpCopy = tmp
|
|
843
833
|
let numLimbs = getSize(tmpCopy)
|
|
844
834
|
tmp = init(numLimbs)
|
|
845
835
|
let mut c = 0N
|
|
846
836
|
let numHalfLimbs = numLimbs << 1n
|
|
847
|
-
for (let mut i = numHalfLimbs - 1n;
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
let (%) = WasmI64.remU
|
|
837
|
+
for (let mut i = numHalfLimbs - 1n; i >= 0n; i -= 1n) {
|
|
838
|
+
use WasmI64.{ (+), divU as (/), remU as (%), (<<) }
|
|
839
|
+
use WasmI32.{ (-) }
|
|
851
840
|
let halfLimb = getHalfLimb(tmpCopy, i)
|
|
852
841
|
// we need this if to exclude the trailing 0 half-limb, if it exists
|
|
853
|
-
if (!(halfLimb == 0n &&
|
|
854
|
-
let tmpInner = WasmI64.extendI32U(halfLimb) +
|
|
842
|
+
if (!(halfLimb == 0n && numHalfLimbs - 1n == i)) {
|
|
843
|
+
let tmpInner = WasmI64.extendI32U(halfLimb) + (c << 32N)
|
|
855
844
|
setHalfLimb(tmp, i, WasmI32.wrapI64(tmpInner / d))
|
|
856
845
|
c = tmpInner % d
|
|
857
846
|
}
|
|
@@ -864,12 +853,10 @@ export let bigIntToString = (num: WasmI32, base: WasmI32) => {
|
|
|
864
853
|
]
|
|
865
854
|
}
|
|
866
855
|
}
|
|
867
|
-
while (
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}
|
|
872
|
-
) {
|
|
856
|
+
while (match (result) {
|
|
857
|
+
[c, ...tl] when DS.untagChar(c) == DS.untagChar('0') => true,
|
|
858
|
+
_ => false,
|
|
859
|
+
}) {
|
|
873
860
|
match (result) {
|
|
874
861
|
[c, ...tl] => result = tl,
|
|
875
862
|
_ => void, // <- impossible
|
|
@@ -882,28 +869,28 @@ export let bigIntToString = (num: WasmI32, base: WasmI32) => {
|
|
|
882
869
|
let rec computeLength = (lst, acc) => {
|
|
883
870
|
match (lst) {
|
|
884
871
|
[] => acc,
|
|
885
|
-
[_, ...tl] => computeLength(tl,
|
|
872
|
+
[_, ...tl] => computeLength(tl, acc + 1n),
|
|
886
873
|
}
|
|
887
874
|
}
|
|
888
875
|
let length = computeLength(result, 0n)
|
|
889
876
|
let ret = DS.allocateString(length)
|
|
890
877
|
@unsafe
|
|
891
|
-
let rec populateString = (lst, idx) => {
|
|
878
|
+
let rec populateString = (lst, idx, str) => {
|
|
892
879
|
match (lst) {
|
|
893
880
|
[] => void,
|
|
894
881
|
[hd, ...tl] => {
|
|
895
|
-
WasmI32.store8(
|
|
896
|
-
populateString(tl,
|
|
882
|
+
WasmI32.store8(str + idx, DS.untagChar(hd), 8n)
|
|
883
|
+
populateString(tl, idx + 1n, str)
|
|
897
884
|
},
|
|
898
885
|
}
|
|
899
886
|
}
|
|
900
|
-
populateString(result, 0n)
|
|
887
|
+
populateString(result, 0n, ret)
|
|
901
888
|
WasmI32.toGrain(ret): String
|
|
902
889
|
}
|
|
903
890
|
}
|
|
904
891
|
|
|
905
892
|
@unsafe
|
|
906
|
-
|
|
893
|
+
provide let bigIntToString10 = (num: WasmI32) => {
|
|
907
894
|
bigIntToString(num, 10n)
|
|
908
895
|
}
|
|
909
896
|
|
|
@@ -913,18 +900,15 @@ export let bigIntToString10 = (num: WasmI32) => {
|
|
|
913
900
|
|
|
914
901
|
@unsafe
|
|
915
902
|
let unsignedAdd = (num1: WasmI32, num2: WasmI32) => {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
let (|) = WasmI32.or
|
|
919
|
-
let (&) = WasmI32.and
|
|
920
|
-
let (+) = WasmI64.add
|
|
921
|
-
let (==) = WasmI32.eq
|
|
903
|
+
use WasmI64.{ (!=) }
|
|
904
|
+
use WasmI32.{ (+), (&), (|), ltU as (<), geU as (>=), (==) }
|
|
922
905
|
let num1Limbs = getSize(num1)
|
|
923
906
|
let num2Limbs = getSize(num2)
|
|
924
907
|
let n = maxu32(num1Limbs, num2Limbs)
|
|
925
908
|
let mut dest = init(n)
|
|
926
909
|
let mut carry = 0N
|
|
927
|
-
for (let mut i = 0n; i < n; i
|
|
910
|
+
for (let mut i = 0n; i < n; i += 1n) {
|
|
911
|
+
use WasmI64.{ (+) }
|
|
928
912
|
let limb1 = if (i >= num1Limbs) {
|
|
929
913
|
0N
|
|
930
914
|
} else {
|
|
@@ -937,12 +921,12 @@ let unsignedAdd = (num1: WasmI32, num2: WasmI32) => {
|
|
|
937
921
|
}
|
|
938
922
|
let z = limb1 + limb2 + carry
|
|
939
923
|
setLimb(dest, i, z)
|
|
940
|
-
|
|
924
|
+
use WasmI64.{ ltU as (<) }
|
|
941
925
|
carry = if (z < limb1 || z < limb2 || z < carry) 1N else 0N
|
|
942
926
|
}
|
|
943
927
|
// handle remaining carry (resize if needed)
|
|
944
|
-
if (
|
|
945
|
-
dest = cloneWithLen(dest,
|
|
928
|
+
if (carry != 0N) {
|
|
929
|
+
dest = cloneWithLen(dest, n + 1n)
|
|
946
930
|
setLimb(dest, n, carry)
|
|
947
931
|
}
|
|
948
932
|
dest
|
|
@@ -950,18 +934,14 @@ let unsignedAdd = (num1: WasmI32, num2: WasmI32) => {
|
|
|
950
934
|
|
|
951
935
|
@unsafe
|
|
952
936
|
let unsignedAddInt = (num1: WasmI32, int: WasmI64) => {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
let (>) = WasmI32.gtU
|
|
956
|
-
let (|) = WasmI32.or
|
|
957
|
-
let (&) = WasmI32.and
|
|
958
|
-
let (+) = WasmI64.add
|
|
959
|
-
let (==) = WasmI32.eq
|
|
937
|
+
use WasmI64.{ (!=) }
|
|
938
|
+
use WasmI32.{ (+), (&), (|), gtU as (>), ltU as (<), geU as (>=), (==) }
|
|
960
939
|
let num1Limbs = getSize(num1)
|
|
961
940
|
let n = maxu32(num1Limbs, 1n)
|
|
962
941
|
let mut dest = init(n)
|
|
963
942
|
let mut carry = 0N
|
|
964
|
-
for (let mut i = 0n; i < n; i
|
|
943
|
+
for (let mut i = 0n; i < n; i += 1n) {
|
|
944
|
+
use WasmI64.{ (+) }
|
|
965
945
|
let limb1 = if (i >= num1Limbs) {
|
|
966
946
|
0N
|
|
967
947
|
} else {
|
|
@@ -974,14 +954,11 @@ let unsignedAddInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
974
954
|
}
|
|
975
955
|
let z = limb1 + limb2 + carry
|
|
976
956
|
setLimb(dest, i, z)
|
|
977
|
-
|
|
957
|
+
use WasmI64.{ ltU as (<) }
|
|
978
958
|
carry = if (z < limb1 || z < limb2 || z < carry) 1N else 0N
|
|
979
|
-
|
|
980
|
-
if (WasmI64.eqz(carry) && i <
|
|
959
|
+
use WasmI32.{ ltU as (<), (-), (+), (*) }
|
|
960
|
+
if (WasmI64.eqz(carry) && i < n - 1n) {
|
|
981
961
|
// if we're not carrying, then there's nothing left to do but copy
|
|
982
|
-
let (+) = WasmI32.add
|
|
983
|
-
let (*) = WasmI32.mul
|
|
984
|
-
let (-) = WasmI32.sub
|
|
985
962
|
Memory.copy(
|
|
986
963
|
dest + 16n + 8n * (i + 1n),
|
|
987
964
|
num1 + 16n + 8n * (i + 1n),
|
|
@@ -991,8 +968,8 @@ let unsignedAddInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
991
968
|
}
|
|
992
969
|
}
|
|
993
970
|
// handle remaining carry (resize if needed)
|
|
994
|
-
if (
|
|
995
|
-
dest = cloneWithLen(dest,
|
|
971
|
+
if (carry != 0N) {
|
|
972
|
+
dest = cloneWithLen(dest, n + 1n)
|
|
996
973
|
setLimb(dest, n, carry)
|
|
997
974
|
}
|
|
998
975
|
dest
|
|
@@ -1000,20 +977,15 @@ let unsignedAddInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
1000
977
|
|
|
1001
978
|
@unsafe
|
|
1002
979
|
let unsignedSubImpl = (num1: WasmI32, num2: WasmI32) => {
|
|
1003
|
-
|
|
1004
|
-
let (>=) = WasmI32.geU
|
|
1005
|
-
let (|) = WasmI32.or
|
|
1006
|
-
let (&) = WasmI32.and
|
|
1007
|
-
let (+) = WasmI64.add
|
|
1008
|
-
let (-) = WasmI64.sub
|
|
1009
|
-
let (==) = WasmI32.eq
|
|
980
|
+
use WasmI32.{ (+), (&), (|), ltU as (<), geU as (>=), (==) }
|
|
1010
981
|
let num1Limbs = getSize(num1)
|
|
1011
982
|
let num2Limbs = getSize(num2)
|
|
1012
983
|
let m = minu32(num1Limbs, num2Limbs)
|
|
1013
984
|
let n = maxu32(num1Limbs, num2Limbs)
|
|
1014
985
|
let mut dest = init(n)
|
|
1015
986
|
let mut carry = 0N
|
|
1016
|
-
for (let mut i = 0n; i < n; i
|
|
987
|
+
for (let mut i = 0n; i < n; i += 1n) {
|
|
988
|
+
use WasmI64.{ (+), (-) }
|
|
1017
989
|
let limb1 = if (i >= num1Limbs) {
|
|
1018
990
|
0N
|
|
1019
991
|
} else {
|
|
@@ -1025,7 +997,7 @@ let unsignedSubImpl = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1025
997
|
getLimb(num2, i)
|
|
1026
998
|
}
|
|
1027
999
|
let z1 = limb1 - limb2
|
|
1028
|
-
|
|
1000
|
+
use WasmI64.{ gtU as (>) }
|
|
1029
1001
|
let carry1 = z1 > limb1
|
|
1030
1002
|
let z = z1 - carry
|
|
1031
1003
|
let carry2 = z > z1
|
|
@@ -1042,8 +1014,7 @@ let unsignedSubImpl = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1042
1014
|
@unsafe
|
|
1043
1015
|
let unsignedSub = (num1: WasmI32, num2: WasmI32) => {
|
|
1044
1016
|
let cmpRes = cmpUnsigned(num1, num2)
|
|
1045
|
-
|
|
1046
|
-
let (<) = WasmI32.ltS
|
|
1017
|
+
use WasmI32.{ (>), (<) }
|
|
1047
1018
|
if (cmpRes > 0n) {
|
|
1048
1019
|
unsignedSubImpl(num1, num2)
|
|
1049
1020
|
} else if (cmpRes < 0n) {
|
|
@@ -1057,20 +1028,14 @@ let unsignedSub = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1057
1028
|
|
|
1058
1029
|
@unsafe
|
|
1059
1030
|
let unsignedSubIntImpl = (num1: WasmI32, int: WasmI64) => {
|
|
1060
|
-
|
|
1061
|
-
let (>=) = WasmI32.geU
|
|
1062
|
-
let (>) = WasmI32.gtU
|
|
1063
|
-
let (|) = WasmI32.or
|
|
1064
|
-
let (&) = WasmI32.and
|
|
1065
|
-
let (+) = WasmI64.add
|
|
1066
|
-
let (-) = WasmI64.sub
|
|
1067
|
-
let (==) = WasmI32.eq
|
|
1031
|
+
use WasmI32.{ (+), (&), (|), ltU as (<), gtU as (>), geU as (>=), (==) }
|
|
1068
1032
|
let num1Limbs = getSize(num1)
|
|
1069
1033
|
let num2Limbs = 1n
|
|
1070
1034
|
let n = maxu32(num1Limbs, 1n)
|
|
1071
1035
|
let mut dest = init(n)
|
|
1072
1036
|
let mut carry = 0N
|
|
1073
|
-
for (let mut i = 0n; i < n; i
|
|
1037
|
+
for (let mut i = 0n; i < n; i += 1n) {
|
|
1038
|
+
use WasmI64.{ (+), (-) }
|
|
1074
1039
|
let limb1 = if (i >= num1Limbs) {
|
|
1075
1040
|
0N
|
|
1076
1041
|
} else {
|
|
@@ -1082,17 +1047,15 @@ let unsignedSubIntImpl = (num1: WasmI32, int: WasmI64) => {
|
|
|
1082
1047
|
int
|
|
1083
1048
|
}
|
|
1084
1049
|
let z1 = limb1 - limb2
|
|
1085
|
-
|
|
1050
|
+
use WasmI64.{ gtU as (>) }
|
|
1086
1051
|
let carry1 = z1 > limb1
|
|
1087
1052
|
let z = z1 - carry
|
|
1088
1053
|
let carry2 = z > z1
|
|
1089
1054
|
setLimb(dest, i, z)
|
|
1090
1055
|
carry = if (carry1 || carry2) 1N else 0N
|
|
1091
|
-
|
|
1056
|
+
use WasmI32.{ (+), (-), (*) }
|
|
1057
|
+
if (WasmI64.eqz(carry) && i < n - 1n) {
|
|
1092
1058
|
// if we're not carrying, then there's nothing left to do but copy
|
|
1093
|
-
let (+) = WasmI32.add
|
|
1094
|
-
let (*) = WasmI32.mul
|
|
1095
|
-
let (-) = WasmI32.sub
|
|
1096
1059
|
Memory.copy(
|
|
1097
1060
|
dest + 16n + 8n * (i + 1n),
|
|
1098
1061
|
num1 + 16n + 8n * (i + 1n),
|
|
@@ -1111,24 +1074,17 @@ let unsignedSubIntImpl = (num1: WasmI32, int: WasmI64) => {
|
|
|
1111
1074
|
@unsafe
|
|
1112
1075
|
let unsignedSubInt = (num1: WasmI32, int: WasmI64) => {
|
|
1113
1076
|
let num1Limbs = getSize(num1)
|
|
1114
|
-
|
|
1115
|
-
|
|
1077
|
+
use WasmI32.{ (==) }
|
|
1078
|
+
use WasmI64.{ (==) as eqWasmI64, (-), ltU as (<) }
|
|
1116
1079
|
if (num1Limbs == 0n || num1Limbs == 1n && getLimb(num1, 0n) < int) {
|
|
1117
1080
|
let ret = init(1n)
|
|
1118
|
-
setLimb(
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if (num1Limbs == 0n) {
|
|
1124
|
-
0N
|
|
1125
|
-
} else {
|
|
1126
|
-
getLimb(num1, 0n)
|
|
1127
|
-
}
|
|
1128
|
-
)
|
|
1129
|
-
)
|
|
1081
|
+
setLimb(ret, 0n, int - (if (num1Limbs == 0n) {
|
|
1082
|
+
0N
|
|
1083
|
+
} else {
|
|
1084
|
+
getLimb(num1, 0n)
|
|
1085
|
+
}))
|
|
1130
1086
|
trimNumberInPlace(negateInPlace(ret))
|
|
1131
|
-
} else if (num1Limbs == 1n &&
|
|
1087
|
+
} else if (num1Limbs == 1n && eqWasmI64(getLimb(num1, 0n), int)) {
|
|
1132
1088
|
makeZero()
|
|
1133
1089
|
} else {
|
|
1134
1090
|
unsignedSubIntImpl(num1, int)
|
|
@@ -1136,7 +1092,7 @@ let unsignedSubInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
1136
1092
|
}
|
|
1137
1093
|
|
|
1138
1094
|
@unsafe
|
|
1139
|
-
|
|
1095
|
+
provide let add = (num1: WasmI32, num2: WasmI32) => {
|
|
1140
1096
|
if (flagIsSet(num1, _IS_NEGATIVE)) {
|
|
1141
1097
|
if (flagIsSet(num2, _IS_NEGATIVE)) {
|
|
1142
1098
|
let ret = unsignedAdd(num1, num2)
|
|
@@ -1155,25 +1111,26 @@ export let add = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1155
1111
|
}
|
|
1156
1112
|
|
|
1157
1113
|
@unsafe
|
|
1158
|
-
|
|
1114
|
+
provide let addInt = (num1: WasmI32, int: WasmI64) => {
|
|
1115
|
+
use WasmI64.{ (+), (^), (<) }
|
|
1159
1116
|
// int is *signed*
|
|
1160
1117
|
if (eqz(num1)) {
|
|
1161
1118
|
let ret = makeWrappedUint64(int)
|
|
1162
|
-
if (
|
|
1119
|
+
if (int < 0N) {
|
|
1163
1120
|
setFlag(ret, _IS_NEGATIVE, 1n)
|
|
1164
1121
|
}
|
|
1165
1122
|
ret
|
|
1166
1123
|
} else if (flagIsSet(num1, _IS_NEGATIVE)) {
|
|
1167
|
-
let ret = if (
|
|
1168
|
-
unsignedAddInt(num1,
|
|
1124
|
+
let ret = if (int < 0N) {
|
|
1125
|
+
unsignedAddInt(num1, (int ^ _UMAX_I64) + 1N)
|
|
1169
1126
|
} else {
|
|
1170
1127
|
unsignedSubInt(num1, int)
|
|
1171
1128
|
}
|
|
1172
1129
|
negateInPlace(ret)
|
|
1173
1130
|
ret
|
|
1174
1131
|
} else {
|
|
1175
|
-
if (
|
|
1176
|
-
unsignedSubInt(num1,
|
|
1132
|
+
if (int < 0N) {
|
|
1133
|
+
unsignedSubInt(num1, (int ^ _UMAX_I64) + 1N)
|
|
1177
1134
|
} else {
|
|
1178
1135
|
unsignedAddInt(num1, int)
|
|
1179
1136
|
}
|
|
@@ -1181,7 +1138,7 @@ export let addInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
1181
1138
|
}
|
|
1182
1139
|
|
|
1183
1140
|
@unsafe
|
|
1184
|
-
|
|
1141
|
+
provide let sub = (num1: WasmI32, num2: WasmI32) => {
|
|
1185
1142
|
if (flagIsSet(num1, _IS_NEGATIVE)) {
|
|
1186
1143
|
if (flagIsSet(num2, _IS_NEGATIVE)) {
|
|
1187
1144
|
unsignedSub(num2, num1)
|
|
@@ -1200,26 +1157,27 @@ export let sub = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1200
1157
|
}
|
|
1201
1158
|
|
|
1202
1159
|
@unsafe
|
|
1203
|
-
|
|
1160
|
+
provide let subInt = (num1: WasmI32, int: WasmI64) => {
|
|
1161
|
+
use WasmI64.{ (+), (^), (<), (>) }
|
|
1204
1162
|
// int is *signed*
|
|
1205
1163
|
if (eqz(num1)) {
|
|
1206
1164
|
let ret = makeWrappedUint64(int)
|
|
1207
1165
|
// inverse:
|
|
1208
|
-
if (
|
|
1166
|
+
if (int > 0N) {
|
|
1209
1167
|
setFlag(ret, _IS_NEGATIVE, 1n)
|
|
1210
1168
|
}
|
|
1211
1169
|
ret
|
|
1212
1170
|
} else if (flagIsSet(num1, _IS_NEGATIVE)) {
|
|
1213
|
-
let ret = if (
|
|
1214
|
-
unsignedSubInt(num1,
|
|
1171
|
+
let ret = if (int < 0N) {
|
|
1172
|
+
unsignedSubInt(num1, (int ^ _UMAX_I64) + 1N)
|
|
1215
1173
|
} else {
|
|
1216
1174
|
unsignedAddInt(num1, int)
|
|
1217
1175
|
}
|
|
1218
1176
|
negateInPlace(ret)
|
|
1219
1177
|
ret
|
|
1220
1178
|
} else {
|
|
1221
|
-
if (
|
|
1222
|
-
unsignedAddInt(num1,
|
|
1179
|
+
if (int < 0N) {
|
|
1180
|
+
unsignedAddInt(num1, (int ^ _UMAX_I64) + 1N)
|
|
1223
1181
|
} else {
|
|
1224
1182
|
unsignedSubInt(num1, int)
|
|
1225
1183
|
}
|
|
@@ -1227,12 +1185,12 @@ export let subInt = (num1: WasmI32, int: WasmI64) => {
|
|
|
1227
1185
|
}
|
|
1228
1186
|
|
|
1229
1187
|
@unsafe
|
|
1230
|
-
|
|
1188
|
+
provide let incr = (num: WasmI32) => {
|
|
1231
1189
|
addInt(num, 1N)
|
|
1232
1190
|
}
|
|
1233
1191
|
|
|
1234
1192
|
@unsafe
|
|
1235
|
-
|
|
1193
|
+
provide let decr = (num: WasmI32) => {
|
|
1236
1194
|
subInt(num, 1N)
|
|
1237
1195
|
}
|
|
1238
1196
|
|
|
@@ -1243,10 +1201,8 @@ export let decr = (num: WasmI32) => {
|
|
|
1243
1201
|
@unsafe
|
|
1244
1202
|
let unsignedMul = (num1: WasmI32, num2: WasmI32) => {
|
|
1245
1203
|
// num1 >= num2
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
let (*) = WasmI64.mul
|
|
1249
|
-
let (<<) = WasmI32.shl
|
|
1204
|
+
use WasmI32.{ (+), (-), (<<), (==) }
|
|
1205
|
+
use WasmI64.{ (*), (>>>) }
|
|
1250
1206
|
let num1Limbs = getSize(num1)
|
|
1251
1207
|
let num2Limbs = getSize(num2)
|
|
1252
1208
|
let num1HalfLimbs = num1Limbs << 1n
|
|
@@ -1256,42 +1212,37 @@ let unsignedMul = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1256
1212
|
// because 64-bit overflow calculation isn't straightforward (and
|
|
1257
1213
|
// basically requires doing so anyway), we implement this alg with 32-bit half-limbs
|
|
1258
1214
|
for (let mut i = 0n; WasmI32.ltU(i, num1HalfLimbs); i += 1n) {
|
|
1215
|
+
use WasmI64.{ (+) }
|
|
1259
1216
|
let halfLimb1 = getHalfLimb(num1, i)
|
|
1260
1217
|
let halfLimb2 = getHalfLimb(num2, 0n)
|
|
1261
|
-
tmp
|
|
1262
|
-
tmp,
|
|
1263
|
-
WasmI64.extendI32U(halfLimb1) * WasmI64.extendI32U(halfLimb2)
|
|
1264
|
-
)
|
|
1218
|
+
tmp += WasmI64.extendI32U(halfLimb1) * WasmI64.extendI32U(halfLimb2)
|
|
1265
1219
|
setHalfLimb(dest, i, WasmI32.wrapI64(tmp))
|
|
1266
|
-
tmp =
|
|
1220
|
+
tmp = tmp >>> 32N
|
|
1267
1221
|
}
|
|
1268
1222
|
setHalfLimb(dest, num1HalfLimbs, WasmI32.wrapI64(tmp))
|
|
1269
1223
|
for (let mut j = 1n; WasmI32.ltU(j, num2HalfLimbs); j += 1n) {
|
|
1270
1224
|
tmp = 0N
|
|
1271
1225
|
let halfLimb2 = getHalfLimb(num2, j)
|
|
1272
|
-
if (
|
|
1273
|
-
WasmI32.eq(j, WasmI32.sub(num2HalfLimbs, 1n)) && WasmI32.eq(halfLimb2, 0n)
|
|
1274
|
-
) {
|
|
1226
|
+
if (j == num2HalfLimbs - 1n && halfLimb2 == 0n) {
|
|
1275
1227
|
break
|
|
1276
1228
|
}
|
|
1277
1229
|
for (let mut i = 0n; WasmI32.ltU(i, num1HalfLimbs); i += 1n) {
|
|
1278
1230
|
let curHalfLimb = getHalfLimb(dest, j + i)
|
|
1279
1231
|
let halfLimb1 = getHalfLimb(num1, i)
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
WasmI64.
|
|
1283
|
-
|
|
1284
|
-
WasmI64.extendI32U(halfLimb1) * WasmI64.extendI32U(halfLimb2)
|
|
1285
|
-
)
|
|
1286
|
-
)
|
|
1232
|
+
use WasmI64.{ (+) }
|
|
1233
|
+
tmp += WasmI64.extendI32U(curHalfLimb) +
|
|
1234
|
+
WasmI64.extendI32U(halfLimb1) * WasmI64.extendI32U(halfLimb2)
|
|
1235
|
+
use WasmI32.{ (+) }
|
|
1287
1236
|
setHalfLimb(dest, j + i, WasmI32.wrapI64(tmp))
|
|
1288
|
-
tmp =
|
|
1237
|
+
tmp = tmp >>> 32N
|
|
1289
1238
|
}
|
|
1290
1239
|
let mut pos = j + num1HalfLimbs
|
|
1291
1240
|
while (WasmI64.gtU(tmp, 0N)) {
|
|
1292
|
-
|
|
1241
|
+
use WasmI64.{ (+) }
|
|
1242
|
+
tmp += WasmI64.extendI32U(getHalfLimb(dest, pos))
|
|
1243
|
+
use WasmI32.{ (+) }
|
|
1293
1244
|
setHalfLimb(dest, pos, WasmI32.wrapI64(tmp))
|
|
1294
|
-
tmp =
|
|
1245
|
+
tmp = tmp >>> 32N
|
|
1295
1246
|
pos += 1n
|
|
1296
1247
|
}
|
|
1297
1248
|
}
|
|
@@ -1300,7 +1251,8 @@ let unsignedMul = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1300
1251
|
|
|
1301
1252
|
// TODO(#1189): Replace with Karatsuba multiplication
|
|
1302
1253
|
@unsafe
|
|
1303
|
-
|
|
1254
|
+
provide let mul = (num1: WasmI32, num2: WasmI32) => {
|
|
1255
|
+
use WasmI32.{ (^) }
|
|
1304
1256
|
let ret = if (eqz(num1) || eqz(num2)) {
|
|
1305
1257
|
makeZero()
|
|
1306
1258
|
} else {
|
|
@@ -1315,7 +1267,7 @@ export let mul = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1315
1267
|
setFlag(
|
|
1316
1268
|
ret,
|
|
1317
1269
|
_IS_NEGATIVE,
|
|
1318
|
-
|
|
1270
|
+
getFlag(num1, _IS_NEGATIVE) ^ getFlag(num2, _IS_NEGATIVE)
|
|
1319
1271
|
)
|
|
1320
1272
|
ret
|
|
1321
1273
|
}
|
|
@@ -1325,42 +1277,38 @@ export let mul = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1325
1277
|
*/
|
|
1326
1278
|
|
|
1327
1279
|
@unsafe
|
|
1328
|
-
|
|
1280
|
+
provide let shl = (num: WasmI32, places: WasmI32) => {
|
|
1281
|
+
use WasmI32.{ (+), divU as (/), remU as (%), ltU as (<) }
|
|
1282
|
+
use WasmI64.{ (-), (&), (|), (<<) }
|
|
1329
1283
|
// places is *unsigned*
|
|
1330
1284
|
let numLimbs = getSize(num)
|
|
1331
1285
|
let mut carry = 0N
|
|
1332
|
-
let (+) = WasmI32.add
|
|
1333
|
-
let (-) = WasmI64.sub
|
|
1334
|
-
let (/) = WasmI32.divU
|
|
1335
|
-
let (%) = WasmI32.remU
|
|
1336
|
-
let (<<) = WasmI64.shl
|
|
1337
|
-
let (<) = WasmI32.ltU
|
|
1338
|
-
let (|) = WasmI64.or
|
|
1339
|
-
let (&) = WasmI64.and
|
|
1340
1286
|
let a = places / 32n
|
|
1341
1287
|
let b = places % 32n
|
|
1342
|
-
let mask = ((1N << WasmI64.extendI32U(b)) - 1N) <<
|
|
1288
|
+
let mask = ((1N << WasmI64.extendI32U(b)) - 1N) <<
|
|
1289
|
+
(64N - WasmI64.extendI32U(b))
|
|
1343
1290
|
let result = init(numLimbs + a)
|
|
1344
1291
|
setFlag(result, _IS_NEGATIVE, getFlag(num, _IS_NEGATIVE))
|
|
1345
|
-
|
|
1292
|
+
use WasmI32.{ (<<) }
|
|
1293
|
+
let numHalfLimbs = numLimbs << 1n
|
|
1346
1294
|
for (let mut i = 0n; i < numHalfLimbs; i += 1n) {
|
|
1295
|
+
use WasmI64.{ (>>>), (<<) }
|
|
1347
1296
|
let acc = WasmI64.extendI32U(getHalfLimb(num, i)) << 32N | carry
|
|
1348
|
-
|
|
1349
|
-
carry = (acc & mask) >> 32N
|
|
1297
|
+
carry = (acc & mask) >>> 32N
|
|
1350
1298
|
setHalfLimb(
|
|
1351
1299
|
result,
|
|
1352
1300
|
i + a,
|
|
1353
|
-
WasmI32.wrapI64((acc << WasmI64.extendI32U(b))
|
|
1301
|
+
WasmI32.wrapI64((acc << WasmI64.extendI32U(b)) >>> 32N)
|
|
1354
1302
|
)
|
|
1355
1303
|
}
|
|
1356
|
-
|
|
1304
|
+
use WasmI64.{ gtU as (>) }
|
|
1357
1305
|
let ret = if (carry > 0N) {
|
|
1358
1306
|
let ret = cloneWithLen(result, numLimbs + a + 1n)
|
|
1359
|
-
|
|
1307
|
+
use WasmI64.{ (>>>) }
|
|
1360
1308
|
setHalfLimb(
|
|
1361
1309
|
ret,
|
|
1362
1310
|
numHalfLimbs + a,
|
|
1363
|
-
WasmI32.wrapI64(carry
|
|
1311
|
+
WasmI32.wrapI64(carry >>> (32N - WasmI64.extendI32U(b)))
|
|
1364
1312
|
)
|
|
1365
1313
|
ret
|
|
1366
1314
|
} else {
|
|
@@ -1370,19 +1318,11 @@ export let shl = (num: WasmI32, places: WasmI32) => {
|
|
|
1370
1318
|
}
|
|
1371
1319
|
|
|
1372
1320
|
@unsafe
|
|
1373
|
-
|
|
1321
|
+
provide let shrS = (num: WasmI32, places: WasmI32) => {
|
|
1374
1322
|
// places is *unsigned*
|
|
1375
1323
|
let numLimbs = getSize(num)
|
|
1376
1324
|
let mut carry = 0N
|
|
1377
|
-
|
|
1378
|
-
let (-) = WasmI32.sub
|
|
1379
|
-
let (/) = WasmI32.divU
|
|
1380
|
-
let (%) = WasmI32.remU
|
|
1381
|
-
let (<<) = WasmI32.shl
|
|
1382
|
-
let (>>) = WasmI64.shrU
|
|
1383
|
-
let (>=) = WasmI32.geS
|
|
1384
|
-
let (|) = WasmI64.or
|
|
1385
|
-
let (&) = WasmI64.and
|
|
1325
|
+
use WasmI32.{ (+), (-), divU as (/), remU as (%), (&), (<<), (>>>), (>=) }
|
|
1386
1326
|
let a = places / 32n
|
|
1387
1327
|
let b = places % 32n
|
|
1388
1328
|
let mask = (1n << b) - 1n
|
|
@@ -1397,30 +1337,26 @@ export let shrS = (num: WasmI32, places: WasmI32) => {
|
|
|
1397
1337
|
} else {
|
|
1398
1338
|
let newHalfLimbs = numHalfLimbs - a
|
|
1399
1339
|
let ret = init(
|
|
1400
|
-
WasmI32.
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
1n
|
|
1406
|
-
}
|
|
1407
|
-
)
|
|
1340
|
+
(newHalfLimbs >>> 1n) + (if (WasmI32.eqz(newHalfLimbs & 1n)) {
|
|
1341
|
+
0n
|
|
1342
|
+
} else {
|
|
1343
|
+
1n
|
|
1344
|
+
})
|
|
1408
1345
|
)
|
|
1409
1346
|
setFlag(ret, _IS_NEGATIVE, getFlag(num, _IS_NEGATIVE))
|
|
1410
1347
|
for (let mut i = numHalfLimbs - 1n; i >= a; i -= 1n) {
|
|
1411
|
-
|
|
1412
|
-
let (|) = WasmI64.or
|
|
1348
|
+
use WasmI64.{ (&), (<<), (|), (>>>) }
|
|
1413
1349
|
let acc = carry << 32N | WasmI64.extendI32U(getHalfLimb(num, i))
|
|
1414
1350
|
carry = acc & WasmI64.extendI32U(mask)
|
|
1415
|
-
setHalfLimb(ret, i - a, WasmI32.wrapI64(acc
|
|
1351
|
+
setHalfLimb(ret, i - a, WasmI32.wrapI64(acc >>> WasmI64.extendI32U(b)))
|
|
1416
1352
|
}
|
|
1417
1353
|
let ret = if (flagIsSet(ret, _IS_NEGATIVE)) {
|
|
1418
1354
|
let mut underflow = false
|
|
1419
|
-
|
|
1355
|
+
use WasmI64.{ gtU as (>) }
|
|
1420
1356
|
if (carry > 0N) {
|
|
1421
1357
|
underflow = true
|
|
1422
1358
|
} else {
|
|
1423
|
-
|
|
1359
|
+
use WasmI32.{ ltU as (<) }
|
|
1424
1360
|
for (let mut i = 0n; i < a; i += 1n) {
|
|
1425
1361
|
if (0n < getHalfLimb(ret, i)) {
|
|
1426
1362
|
underflow = true
|
|
@@ -1449,9 +1385,8 @@ let bitwiseNotUnsigned = (num: WasmI32) => {
|
|
|
1449
1385
|
// but `bitwiseNot` is the user-facing bitwise NOT implementation
|
|
1450
1386
|
let num1Limbs = getSize(num)
|
|
1451
1387
|
let ret = init(num1Limbs)
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
let (^) = WasmI64.xor
|
|
1388
|
+
use WasmI32.{ (+), ltU as (<) }
|
|
1389
|
+
use WasmI64.{ (^) }
|
|
1455
1390
|
for (let mut i = 0n; i < num1Limbs; i += 1n) {
|
|
1456
1391
|
setLimb(ret, i, getLimb(num, i) ^ _UMAX_I64)
|
|
1457
1392
|
}
|
|
@@ -1459,21 +1394,14 @@ let bitwiseNotUnsigned = (num: WasmI32) => {
|
|
|
1459
1394
|
}
|
|
1460
1395
|
|
|
1461
1396
|
@unsafe
|
|
1462
|
-
let bitwiseAndPositive =
|
|
1463
|
-
(
|
|
1464
|
-
num1: WasmI32,
|
|
1465
|
-
num2: WasmI32,
|
|
1466
|
-
copyTrailing: WasmI32,
|
|
1467
|
-
) => {
|
|
1397
|
+
let bitwiseAndPositive = (num1: WasmI32, num2: WasmI32, copyTrailing: WasmI32) => {
|
|
1468
1398
|
// bitwise and, but both num1 and num2 are assumed to be positive
|
|
1469
1399
|
let num1Limbs = getSize(num1)
|
|
1470
1400
|
let num2Limbs = getSize(num2)
|
|
1471
1401
|
let newLimbs = maxu32(num1Limbs, num2Limbs)
|
|
1472
1402
|
let ret = init(newLimbs)
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
let (&) = WasmI64.and
|
|
1476
|
-
let (==) = WasmI32.eq
|
|
1403
|
+
use WasmI32.{ (+), ltU as (<), (==) }
|
|
1404
|
+
use WasmI64.{ (&) }
|
|
1477
1405
|
let numToProcess = minu32(num1Limbs, num2Limbs) // anything past this is 0
|
|
1478
1406
|
for (let mut i = 0n; i < numToProcess; i += 1n) {
|
|
1479
1407
|
setLimb(ret, i, getLimb(num1, i) & getLimb(num2, i))
|
|
@@ -1500,9 +1428,8 @@ let bitwiseOrPositive = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1500
1428
|
let num2Limbs = getSize(num2)
|
|
1501
1429
|
let newLimbs = maxu32(num1Limbs, num2Limbs)
|
|
1502
1430
|
let ret = init(newLimbs)
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
let (|) = WasmI64.or
|
|
1431
|
+
use WasmI32.{ (+), ltU as (<) }
|
|
1432
|
+
use WasmI64.{ (|) }
|
|
1506
1433
|
for (let mut i = 0n; i < newLimbs; i += 1n) {
|
|
1507
1434
|
let limb1 = if (i < num1Limbs) getLimb(num1, i) else 0N
|
|
1508
1435
|
let limb2 = if (i < num2Limbs) getLimb(num2, i) else 0N
|
|
@@ -1518,9 +1445,8 @@ let bitwiseXorPositive = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1518
1445
|
let num2Limbs = getSize(num2)
|
|
1519
1446
|
let newLimbs = maxu32(num1Limbs, num2Limbs)
|
|
1520
1447
|
let ret = init(newLimbs)
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
let (^) = WasmI64.xor
|
|
1448
|
+
use WasmI32.{ (+), ltU as (<) }
|
|
1449
|
+
use WasmI64.{ (^) }
|
|
1524
1450
|
for (let mut i = 0n; i < newLimbs; i += 1n) {
|
|
1525
1451
|
let limb1 = if (i < num1Limbs) getLimb(num1, i) else 0N
|
|
1526
1452
|
let limb2 = if (i < num2Limbs) getLimb(num2, i) else 0N
|
|
@@ -1532,7 +1458,7 @@ let bitwiseXorPositive = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1532
1458
|
// https://stackoverflow.com/a/32298732
|
|
1533
1459
|
|
|
1534
1460
|
@unsafe
|
|
1535
|
-
|
|
1461
|
+
provide let bitwiseNot = (num: WasmI32) => {
|
|
1536
1462
|
// ~x == -x - 1
|
|
1537
1463
|
let numNegated = negate(num)
|
|
1538
1464
|
let result = decr(numNegated)
|
|
@@ -1541,7 +1467,7 @@ export let bitwiseNot = (num: WasmI32) => {
|
|
|
1541
1467
|
}
|
|
1542
1468
|
|
|
1543
1469
|
@unsafe
|
|
1544
|
-
|
|
1470
|
+
provide let bitwiseAnd = (num1: WasmI32, num2: WasmI32) => {
|
|
1545
1471
|
let num1 = WasmI32.fromGrain(num1)
|
|
1546
1472
|
let num2 = WasmI32.fromGrain(num2)
|
|
1547
1473
|
let ret = if (!flagIsSet(num1, _IS_NEGATIVE)) {
|
|
@@ -1592,7 +1518,7 @@ export let bitwiseAnd = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1592
1518
|
}
|
|
1593
1519
|
|
|
1594
1520
|
@unsafe
|
|
1595
|
-
|
|
1521
|
+
provide let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
|
|
1596
1522
|
let num1 = WasmI32.fromGrain(num1)
|
|
1597
1523
|
let num2 = WasmI32.fromGrain(num2)
|
|
1598
1524
|
let ret = if (!flagIsSet(num1, _IS_NEGATIVE)) {
|
|
@@ -1633,11 +1559,7 @@ export let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1633
1559
|
let num2Neg = negate(num2) // B
|
|
1634
1560
|
let num1Sub1 = decr(num1Neg) // (A-1)
|
|
1635
1561
|
let num2Sub1 = decr(num2Neg) // (B-1)
|
|
1636
|
-
let andResult = bitwiseAndPositive(
|
|
1637
|
-
num1Sub1,
|
|
1638
|
-
num2Sub1,
|
|
1639
|
-
0n
|
|
1640
|
-
) // (A-1) & (B-1)
|
|
1562
|
+
let andResult = bitwiseAndPositive(num1Sub1, num2Sub1, 0n) // (A-1) & (B-1)
|
|
1641
1563
|
let ret = incr(andResult) // ((A-1) & (B-1)) + 1
|
|
1642
1564
|
Memory.decRef(num1Neg)
|
|
1643
1565
|
Memory.decRef(num2Neg)
|
|
@@ -1653,7 +1575,7 @@ export let bitwiseOr = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1653
1575
|
}
|
|
1654
1576
|
|
|
1655
1577
|
@unsafe
|
|
1656
|
-
|
|
1578
|
+
provide let bitwiseXor = (num1: WasmI32, num2: WasmI32) => {
|
|
1657
1579
|
let num1 = WasmI32.fromGrain(num1)
|
|
1658
1580
|
let num2 = WasmI32.fromGrain(num2)
|
|
1659
1581
|
let ret = if (!flagIsSet(num1, _IS_NEGATIVE)) {
|
|
@@ -1704,7 +1626,7 @@ export let bitwiseXor = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1704
1626
|
}
|
|
1705
1627
|
|
|
1706
1628
|
@unsafe
|
|
1707
|
-
|
|
1629
|
+
provide let countLeadingZeros = (num: WasmI32) => {
|
|
1708
1630
|
// if positive, there are an infinite number. if negative, there are none.
|
|
1709
1631
|
if (flagIsSet(num, _IS_NEGATIVE)) {
|
|
1710
1632
|
0n
|
|
@@ -1714,18 +1636,16 @@ export let countLeadingZeros = (num: WasmI32) => {
|
|
|
1714
1636
|
}
|
|
1715
1637
|
|
|
1716
1638
|
@unsafe
|
|
1717
|
-
|
|
1639
|
+
provide let countTrailingZeros = (num: WasmI32) => {
|
|
1718
1640
|
// the number of trailing zeros is the same for `x` and `-x` (using two's complement),
|
|
1719
1641
|
// so we can safely ignore the sign.
|
|
1720
1642
|
let numLimbs = getSize(num)
|
|
1721
1643
|
let mut ret = 0N
|
|
1722
|
-
|
|
1723
|
-
let (<) = WasmI32.ltU
|
|
1644
|
+
use WasmI32.{ (+), ltU as (<) }
|
|
1724
1645
|
for (let mut i = 0n; i < numLimbs; i += 1n) {
|
|
1725
1646
|
let limb = getLimb(num, i)
|
|
1726
1647
|
let limbtz = WasmI64.ctz(limb)
|
|
1727
|
-
|
|
1728
|
-
let (+) = WasmI64.add
|
|
1648
|
+
use WasmI64.{ (+), (!=) }
|
|
1729
1649
|
ret += limbtz
|
|
1730
1650
|
if (limbtz != 64N) {
|
|
1731
1651
|
break
|
|
@@ -1735,7 +1655,7 @@ export let countTrailingZeros = (num: WasmI32) => {
|
|
|
1735
1655
|
}
|
|
1736
1656
|
|
|
1737
1657
|
@unsafe
|
|
1738
|
-
|
|
1658
|
+
provide let popcnt = (num: WasmI32, flagDest: WasmI32) => {
|
|
1739
1659
|
// negative numbers have an infinite number of ones, so we return SMAX
|
|
1740
1660
|
if (flagIsSet(num, _IS_NEGATIVE)) {
|
|
1741
1661
|
WasmI32.store(flagDest, 1n, 0n)
|
|
@@ -1743,12 +1663,11 @@ export let popcnt = (num: WasmI32, flagDest: WasmI32) => {
|
|
|
1743
1663
|
} else {
|
|
1744
1664
|
let numLimbs = getSize(num)
|
|
1745
1665
|
let mut ret = 0N
|
|
1746
|
-
|
|
1747
|
-
let (<) = WasmI32.ltU
|
|
1666
|
+
use WasmI32.{ (+), ltU as (<) }
|
|
1748
1667
|
for (let mut i = 0n; i < numLimbs; i += 1n) {
|
|
1668
|
+
use WasmI64.{ (+) }
|
|
1749
1669
|
let limb = getLimb(num, i)
|
|
1750
1670
|
let limbtz = WasmI64.popcnt(limb)
|
|
1751
|
-
let (+) = WasmI64.add
|
|
1752
1671
|
ret += limbtz
|
|
1753
1672
|
}
|
|
1754
1673
|
ret
|
|
@@ -1761,43 +1680,41 @@ export let popcnt = (num: WasmI32, flagDest: WasmI32) => {
|
|
|
1761
1680
|
|
|
1762
1681
|
// BigInt GCD
|
|
1763
1682
|
@unsafe
|
|
1764
|
-
|
|
1683
|
+
provide let gcd = (num1: WasmI32, num2: WasmI32) => {
|
|
1765
1684
|
if (eqz(num1)) {
|
|
1766
|
-
abs(num2)
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1685
|
+
return abs(num2)
|
|
1686
|
+
}
|
|
1687
|
+
if (eqz(num2)) {
|
|
1688
|
+
return abs(num1)
|
|
1689
|
+
}
|
|
1690
|
+
let mut u = abs(num1)
|
|
1691
|
+
let mut v = abs(num2)
|
|
1692
|
+
let i = countTrailingZeroBits(u)
|
|
1693
|
+
let j = countTrailingZeroBits(v)
|
|
1694
|
+
let k = minu32(i, j)
|
|
1695
|
+
let mut newu = shrS(u, i)
|
|
1696
|
+
let mut newv = shrS(v, j)
|
|
1697
|
+
Memory.decRef(u)
|
|
1698
|
+
Memory.decRef(v)
|
|
1699
|
+
u = newu
|
|
1700
|
+
v = newv
|
|
1701
|
+
while (true) {
|
|
1702
|
+
if (gt(u, v)) {
|
|
1703
|
+
let tmp = v
|
|
1704
|
+
v = u
|
|
1705
|
+
u = tmp
|
|
1706
|
+
}
|
|
1707
|
+
newv = sub(v, u)
|
|
1778
1708
|
Memory.decRef(v)
|
|
1779
|
-
u = newu
|
|
1780
1709
|
v = newv
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
if (gt(u, v)) {
|
|
1784
|
-
let tmp = v
|
|
1785
|
-
v = u
|
|
1786
|
-
u = tmp
|
|
1787
|
-
}
|
|
1788
|
-
newv = sub(v, u)
|
|
1789
|
-
Memory.decRef(v)
|
|
1790
|
-
v = newv
|
|
1791
|
-
if (eqz(v)) {
|
|
1792
|
-
ret = shl(u, k)
|
|
1793
|
-
break
|
|
1794
|
-
}
|
|
1795
|
-
newv = shrS(v, countTrailingZeroBits(v))
|
|
1796
|
-
Memory.decRef(v)
|
|
1797
|
-
v = newv
|
|
1710
|
+
if (eqz(v)) {
|
|
1711
|
+
return shl(u, k)
|
|
1798
1712
|
}
|
|
1799
|
-
|
|
1713
|
+
newv = shrS(v, countTrailingZeroBits(v))
|
|
1714
|
+
Memory.decRef(v)
|
|
1715
|
+
v = newv
|
|
1800
1716
|
}
|
|
1717
|
+
return 0n
|
|
1801
1718
|
}
|
|
1802
1719
|
|
|
1803
1720
|
// For division, "normalized" refers to the following (from Brent & Zimmermann):
|
|
@@ -1813,12 +1730,7 @@ export let gcd = (num1: WasmI32, num2: WasmI32) => {
|
|
|
1813
1730
|
// Brent & Zimmermann v0.5.9 Algorithm 1.6 (Chapter 1.4)
|
|
1814
1731
|
@unsafe
|
|
1815
1732
|
let baseCaseDivRem = (a: WasmI32, b: WasmI32, result: WasmI32) => {
|
|
1816
|
-
|
|
1817
|
-
let (-) = WasmI32.sub
|
|
1818
|
-
let (*) = WasmI32.mul
|
|
1819
|
-
let (<<) = WasmI32.shl
|
|
1820
|
-
let (>>) = WasmI32.shrU
|
|
1821
|
-
let (>=) = WasmI32.geS
|
|
1733
|
+
use WasmI32.{ (+), (-), (*), (&), (<<), (>>>), (>=) }
|
|
1822
1734
|
let aOrig = a
|
|
1823
1735
|
// b is `n` half-limbs
|
|
1824
1736
|
// a is `n+m` half-limbs, m >= 0 (i.e. `a` has at least as many limbs as `b`)
|
|
@@ -1826,18 +1738,14 @@ let baseCaseDivRem = (a: WasmI32, b: WasmI32, result: WasmI32) => {
|
|
|
1826
1738
|
// \beta == 2^32 (we use half-limbs in this implementation because it makes calculating qjstar faster)
|
|
1827
1739
|
let n = getHalfSize(b)
|
|
1828
1740
|
let m = getHalfSize(a) - n
|
|
1829
|
-
let qsize = (if (WasmI32.eqz(
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
1n
|
|
1741
|
+
let qsize = (if (WasmI32.eqz(m + 1n & 1n)) {
|
|
1742
|
+
m + 1n
|
|
1743
|
+
} else {
|
|
1744
|
+
m + 2n
|
|
1745
|
+
}) >>> 1n
|
|
1835
1746
|
let mut q = init(qsize)
|
|
1836
1747
|
let mut a = 0n
|
|
1837
|
-
let bTimesBetaM = shl(
|
|
1838
|
-
b,
|
|
1839
|
-
WasmI32.mul(m, 32n)
|
|
1840
|
-
) // b * \beta^m == b * (2^32)^m == b*2^(32*m)
|
|
1748
|
+
let bTimesBetaM = shl(b, m * 32n) // b * \beta^m == b * (2^32)^m == b*2^(32*m)
|
|
1841
1749
|
if (gte(aOrig, bTimesBetaM)) {
|
|
1842
1750
|
setHalfLimb(q, m, 1n)
|
|
1843
1751
|
a = sub(aOrig, bTimesBetaM)
|
|
@@ -1847,21 +1755,13 @@ let baseCaseDivRem = (a: WasmI32, b: WasmI32, result: WasmI32) => {
|
|
|
1847
1755
|
}
|
|
1848
1756
|
Memory.decRef(bTimesBetaM)
|
|
1849
1757
|
for (let mut j = m - 1n; j >= 0n; j -= 1n) {
|
|
1850
|
-
|
|
1851
|
-
let
|
|
1852
|
-
let (/) = WasmI64.divU
|
|
1853
|
-
let anjBeta = WasmI64.extendI32U(getHalfLimb(a, n + j)) <<
|
|
1854
|
-
32N // a_{n+j}\beta
|
|
1758
|
+
use WasmI64.{ divU as (/), (|), (<<) }
|
|
1759
|
+
let anjBeta = WasmI64.extendI32U(getHalfLimb(a, n + j)) << 32N // a_{n+j}\beta
|
|
1855
1760
|
let anj1 = WasmI64.extendI32U(getHalfLimb(a, n + j - 1n)) // a_{n+j-1}
|
|
1856
1761
|
let bn1 = WasmI64.extendI32U(getHalfLimb(b, n - 1n)) // b_{n-1}
|
|
1857
1762
|
let qjstar = (anjBeta | anj1) / bn1 // q_j^\ast (quotient selection)
|
|
1858
|
-
let mut qj = WasmI32.wrapI64(
|
|
1859
|
-
|
|
1860
|
-
) // min(q_j^ast, \beta - 1) (equiv. to qjstar & _UMAX_I6432)
|
|
1861
|
-
let bTimesBetaJ = shl(
|
|
1862
|
-
b,
|
|
1863
|
-
WasmI32.mul(j, 32n)
|
|
1864
|
-
) // b * \beta^j == b * (2^32)^j == b*2^(32*j)
|
|
1763
|
+
let mut qj = WasmI32.wrapI64(qjstar) // min(q_j^ast, \beta - 1) (equiv. to qjstar & _UMAX_I6432)
|
|
1764
|
+
let bTimesBetaJ = shl(b, j * 32n) // b * \beta^j == b * (2^32)^j == b*2^(32*j)
|
|
1865
1765
|
let qjWrapped = makeWrappedUint32(qj)
|
|
1866
1766
|
let qjTimesBTimesBetaJ = mul(bTimesBetaJ, qjWrapped)
|
|
1867
1767
|
Memory.decRef(qjWrapped)
|
|
@@ -1886,8 +1786,7 @@ let baseCaseDivRemUnnormalized = (a: WasmI32, b: WasmI32, result: WasmI32) => {
|
|
|
1886
1786
|
// wrapper around baseCaseDivRem which accepts unnormalized b
|
|
1887
1787
|
// b is `n` half-limbs; n > 0
|
|
1888
1788
|
// a is `n+m` half-limbs, m >= 0 (i.e. `a` has at least as many limbs as `b`)
|
|
1889
|
-
|
|
1890
|
-
let (>) = WasmI32.gtU
|
|
1789
|
+
use WasmI32.{ (-), gtU as (>) }
|
|
1891
1790
|
let n = getHalfSize(b)
|
|
1892
1791
|
//assert !WasmI32.eqz(n)
|
|
1893
1792
|
let mostSignificantHalfLimb = getHalfLimb(b, n - 1n)
|
|
@@ -1908,13 +1807,13 @@ let baseCaseDivRemUnnormalized = (a: WasmI32, b: WasmI32, result: WasmI32) => {
|
|
|
1908
1807
|
}
|
|
1909
1808
|
|
|
1910
1809
|
@unsafe
|
|
1911
|
-
let division =
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
)
|
|
1810
|
+
let division = (
|
|
1811
|
+
num1: WasmI32,
|
|
1812
|
+
num2: WasmI32,
|
|
1813
|
+
destContainer: WasmI32,
|
|
1814
|
+
divMod: Bool,
|
|
1815
|
+
) => {
|
|
1816
|
+
use WasmI32.{ (^), (==) }
|
|
1918
1817
|
if (eqz(num2)) {
|
|
1919
1818
|
throw Exception.DivisionByZero
|
|
1920
1819
|
}
|
|
@@ -1928,24 +1827,16 @@ let division =
|
|
|
1928
1827
|
} else if (WasmI32.ltU(num1HalfLimbs, num2HalfLimbs)) {
|
|
1929
1828
|
q = makeZero()
|
|
1930
1829
|
r = clone(num1)
|
|
1931
|
-
} else if (
|
|
1830
|
+
} else if (num2HalfLimbs == 1n) {
|
|
1932
1831
|
let d = getLimb(num2, 0n)
|
|
1933
|
-
|
|
1934
|
-
let (<<) = WasmI32.shl
|
|
1832
|
+
use WasmI32.{ (+), (-), (<<), (>=) }
|
|
1935
1833
|
q = init(getSize(num1))
|
|
1936
1834
|
let mut r2 = 0N
|
|
1937
|
-
for (
|
|
1938
|
-
|
|
1939
|
-
WasmI32.geS(i, 0n);
|
|
1940
|
-
i = WasmI32.sub(i, 1n)
|
|
1941
|
-
) {
|
|
1942
|
-
let (+) = WasmI64.add
|
|
1943
|
-
let (/) = WasmI64.divU
|
|
1944
|
-
let (%) = WasmI64.remU
|
|
1945
|
-
let (==) = WasmI32.eq
|
|
1835
|
+
for (let mut i = num1HalfLimbs - 1n; i >= 0n; i -= 1n) {
|
|
1836
|
+
use WasmI64.{ (+), divU as (/), remU as (%), (<<) }
|
|
1946
1837
|
let halfLimb = getHalfLimb(num1, i)
|
|
1947
|
-
if (!(halfLimb == 0n &&
|
|
1948
|
-
let tmp = WasmI64.extendI32U(halfLimb) +
|
|
1838
|
+
if (!(halfLimb == 0n && num1HalfLimbs - 1n == i)) {
|
|
1839
|
+
let tmp = WasmI64.extendI32U(halfLimb) + (r2 << 32N)
|
|
1949
1840
|
setHalfLimb(q, i, WasmI32.wrapI64(tmp / d))
|
|
1950
1841
|
r2 = tmp % d
|
|
1951
1842
|
}
|
|
@@ -1974,7 +1865,7 @@ let division =
|
|
|
1974
1865
|
setFlag(
|
|
1975
1866
|
q,
|
|
1976
1867
|
_IS_NEGATIVE,
|
|
1977
|
-
|
|
1868
|
+
getFlag(num1, _IS_NEGATIVE) ^ getFlag(num2, _IS_NEGATIVE)
|
|
1978
1869
|
)
|
|
1979
1870
|
if (flagIsSet(num1, _IS_NEGATIVE) && !eqz(r)) {
|
|
1980
1871
|
setFlag(r, _IS_NEGATIVE, 1n)
|
|
@@ -1983,8 +1874,10 @@ let division =
|
|
|
1983
1874
|
// https://en.wikipedia.org/wiki/Modulo_operation
|
|
1984
1875
|
if (
|
|
1985
1876
|
divMod &&
|
|
1986
|
-
(
|
|
1987
|
-
|
|
1877
|
+
(
|
|
1878
|
+
flagIsSet(r, _IS_NEGATIVE) && !flagIsSet(num2, _IS_NEGATIVE) ||
|
|
1879
|
+
!flagIsSet(r, _IS_NEGATIVE) && flagIsSet(num2, _IS_NEGATIVE)
|
|
1880
|
+
)
|
|
1988
1881
|
) {
|
|
1989
1882
|
let newr = add(r, num2)
|
|
1990
1883
|
Memory.decRef(r)
|
|
@@ -1999,17 +1892,17 @@ let division =
|
|
|
1999
1892
|
}
|
|
2000
1893
|
|
|
2001
1894
|
@unsafe
|
|
2002
|
-
|
|
1895
|
+
provide let quotRem = (num1: WasmI32, num2: WasmI32, dest: WasmI32) => {
|
|
2003
1896
|
division(num1, num2, dest, false)
|
|
2004
1897
|
}
|
|
2005
1898
|
|
|
2006
1899
|
@unsafe
|
|
2007
|
-
|
|
1900
|
+
provide let divMod = (num1: WasmI32, num2: WasmI32, dest: WasmI32) => {
|
|
2008
1901
|
division(num1, num2, dest, true)
|
|
2009
1902
|
}
|
|
2010
1903
|
|
|
2011
1904
|
@unsafe
|
|
2012
|
-
|
|
1905
|
+
provide let quot = (num1: WasmI32, num2: WasmI32) => {
|
|
2013
1906
|
let dest = Memory.malloc(8n)
|
|
2014
1907
|
division(num1, num2, dest, false)
|
|
2015
1908
|
let ret = WasmI32.load(dest, 0n)
|
|
@@ -2018,7 +1911,7 @@ export let quot = (num1: WasmI32, num2: WasmI32) => {
|
|
|
2018
1911
|
}
|
|
2019
1912
|
|
|
2020
1913
|
@unsafe
|
|
2021
|
-
|
|
1914
|
+
provide let div = (num1: WasmI32, num2: WasmI32) => {
|
|
2022
1915
|
let dest = Memory.malloc(8n)
|
|
2023
1916
|
division(num1, num2, dest, true)
|
|
2024
1917
|
let ret = WasmI32.load(dest, 0n)
|
|
@@ -2027,7 +1920,7 @@ export let div = (num1: WasmI32, num2: WasmI32) => {
|
|
|
2027
1920
|
}
|
|
2028
1921
|
|
|
2029
1922
|
@unsafe
|
|
2030
|
-
|
|
1923
|
+
provide let rem = (num1: WasmI32, num2: WasmI32) => {
|
|
2031
1924
|
let dest = Memory.malloc(8n)
|
|
2032
1925
|
division(num1, num2, dest, false)
|
|
2033
1926
|
let ret = WasmI32.load(dest, 4n)
|
|
@@ -2036,7 +1929,7 @@ export let rem = (num1: WasmI32, num2: WasmI32) => {
|
|
|
2036
1929
|
}
|
|
2037
1930
|
|
|
2038
1931
|
@unsafe
|
|
2039
|
-
|
|
1932
|
+
provide let mod = (num1: WasmI32, num2: WasmI32) => {
|
|
2040
1933
|
let dest = Memory.malloc(8n)
|
|
2041
1934
|
division(num1, num2, dest, true)
|
|
2042
1935
|
let ret = WasmI32.load(dest, 4n)
|