@grain/stdlib 0.4.6 → 0.5.2
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 +93 -0
- package/array.gr +18 -18
- package/array.md +18 -18
- package/bigint.gr +497 -0
- package/bigint.md +811 -0
- package/buffer.gr +59 -223
- package/buffer.md +24 -17
- package/bytes.gr +100 -202
- package/bytes.md +19 -0
- package/char.gr +63 -133
- package/exception.gr +28 -2
- package/exception.md +43 -0
- package/float32.gr +76 -95
- package/float32.md +69 -30
- package/float64.gr +81 -95
- package/float64.md +69 -30
- package/hash.gr +37 -37
- package/int32.gr +152 -198
- package/int32.md +104 -0
- package/int64.gr +151 -197
- package/int64.md +104 -0
- package/list.gr +467 -70
- package/list.md +1141 -0
- package/map.gr +192 -7
- package/map.md +525 -0
- package/number.gr +111 -54
- package/number.md +100 -3
- package/option.md +1 -1
- package/package.json +3 -3
- package/pervasives.gr +499 -59
- package/pervasives.md +1116 -0
- package/queue.gr +4 -0
- package/queue.md +10 -0
- package/random.gr +196 -0
- package/random.md +179 -0
- package/regex.gr +1833 -842
- package/regex.md +11 -11
- package/result.md +1 -1
- package/runtime/bigint.gr +2045 -0
- package/runtime/bigint.md +326 -0
- package/runtime/dataStructures.gr +99 -278
- package/runtime/dataStructures.md +391 -0
- package/runtime/debug.md +6 -0
- package/runtime/equal.gr +5 -23
- package/runtime/equal.md +6 -0
- package/runtime/exception.md +30 -0
- package/runtime/gc.gr +20 -3
- package/runtime/gc.md +36 -0
- package/runtime/malloc.gr +13 -11
- package/runtime/malloc.md +55 -0
- package/runtime/numberUtils.gr +91 -41
- package/runtime/numberUtils.md +54 -0
- package/runtime/numbers.gr +1049 -391
- package/runtime/numbers.md +300 -0
- package/runtime/string.gr +136 -230
- package/runtime/string.md +24 -0
- package/runtime/stringUtils.gr +58 -38
- package/runtime/stringUtils.md +6 -0
- package/runtime/unsafe/constants.gr +17 -0
- package/runtime/unsafe/constants.md +72 -0
- package/runtime/unsafe/conv.md +71 -0
- package/runtime/unsafe/errors.md +204 -0
- package/runtime/unsafe/memory.md +54 -0
- package/runtime/unsafe/printWasm.md +24 -0
- package/runtime/unsafe/tags.gr +9 -8
- package/runtime/unsafe/tags.md +120 -0
- package/runtime/unsafe/wasmf32.md +168 -0
- package/runtime/unsafe/wasmf64.md +168 -0
- package/runtime/unsafe/wasmi32.md +282 -0
- package/runtime/unsafe/wasmi64.md +300 -0
- package/runtime/utils/printing.gr +62 -0
- package/runtime/utils/printing.md +18 -0
- package/runtime/wasi.gr +1 -1
- package/runtime/wasi.md +839 -0
- package/set.gr +17 -8
- package/set.md +24 -21
- package/stack.gr +3 -3
- package/stack.md +4 -6
- package/string.gr +194 -329
- package/string.md +3 -3
- package/sys/file.gr +245 -429
- package/sys/process.gr +27 -45
- package/sys/random.gr +47 -16
- package/sys/random.md +38 -0
- package/sys/time.gr +11 -27
package/runtime/numbers.gr
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
/* grainc-flags --
|
|
1
|
+
/* grainc-flags --no-pervasives */
|
|
2
2
|
|
|
3
3
|
import Memory from "runtime/unsafe/memory"
|
|
4
4
|
import Tags from "runtime/unsafe/tags"
|
|
5
5
|
import Exception from "runtime/exception"
|
|
6
|
+
import BI from "runtime/bigint"
|
|
6
7
|
|
|
8
|
+
import {
|
|
9
|
+
_SMAX32_I64 as _I32_MAX,
|
|
10
|
+
_SMIN32_I64 as _I32_MIN,
|
|
11
|
+
} from "runtime/unsafe/constants"
|
|
7
12
|
import WasmI32 from "runtime/unsafe/wasmi32"
|
|
8
13
|
import WasmI64 from "runtime/unsafe/wasmi64"
|
|
9
14
|
import WasmF32 from "runtime/unsafe/wasmf32"
|
|
@@ -24,30 +29,29 @@ import {
|
|
|
24
29
|
newFloat64,
|
|
25
30
|
} from "runtime/dataStructures"
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
export newInt32
|
|
29
|
-
export newInt64
|
|
30
|
-
export newFloat32
|
|
31
|
-
export newFloat64
|
|
32
|
-
|
|
33
|
-
let _I32_MAX = 0x7fffffffN
|
|
34
|
-
let _I32_MIN = -0x7fffffffN
|
|
32
|
+
@unsafe
|
|
35
33
|
let _F32_MAX = 3.40282347e+38W
|
|
34
|
+
@unsafe
|
|
36
35
|
let _F32_MIN = 1.401298464324817e-45W
|
|
36
|
+
@unsafe
|
|
37
37
|
let _F32_MAX_SAFE_INTEGER = 16777215.w
|
|
38
|
+
@unsafe
|
|
38
39
|
let _F64_MAX_SAFE_INTEGER = 9007199254740991.W
|
|
39
40
|
|
|
40
41
|
let (==) = WasmI32.eq
|
|
41
42
|
let (!=) = WasmI32.ne
|
|
42
43
|
|
|
44
|
+
@unsafe
|
|
43
45
|
let tagSimple = x => {
|
|
44
46
|
WasmI32.xor(WasmI32.shl(x, 1n), 1n)
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
@unsafe
|
|
47
50
|
let untagSimple = x => {
|
|
48
51
|
WasmI32.shrS(x, 1n)
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
@unsafe
|
|
51
55
|
let isSimpleNumber = x => {
|
|
52
56
|
WasmI32.eq(
|
|
53
57
|
WasmI32.and(x, Tags._GRAIN_NUMBER_TAG_MASK),
|
|
@@ -55,6 +59,7 @@ let isSimpleNumber = x => {
|
|
|
55
59
|
)
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
@unsafe
|
|
58
63
|
export let isBoxedNumber = x => {
|
|
59
64
|
if (
|
|
60
65
|
WasmI32.eq(
|
|
@@ -68,6 +73,7 @@ export let isBoxedNumber = x => {
|
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
|
|
76
|
+
@unsafe
|
|
71
77
|
export let isFloat = x => {
|
|
72
78
|
if (isBoxedNumber(x)) {
|
|
73
79
|
let tag = WasmI32.load(x, 4n)
|
|
@@ -78,11 +84,23 @@ export let isFloat = x => {
|
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
|
|
87
|
+
@unsafe
|
|
88
|
+
let isBigInt = x => {
|
|
89
|
+
if (isBoxedNumber(x)) {
|
|
90
|
+
let tag = WasmI32.load(x, 4n)
|
|
91
|
+
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG)
|
|
92
|
+
} else {
|
|
93
|
+
false
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@unsafe
|
|
81
98
|
export let isNumber = x => {
|
|
82
99
|
// x is a number if it is a literal number or a boxed_num heap value
|
|
83
100
|
isSimpleNumber(x) || isBoxedNumber(x)
|
|
84
101
|
}
|
|
85
102
|
|
|
103
|
+
@unsafe
|
|
86
104
|
let safeI64toI32 = x => {
|
|
87
105
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
88
106
|
throw Exception.Overflow
|
|
@@ -91,12 +109,16 @@ let safeI64toI32 = x => {
|
|
|
91
109
|
}
|
|
92
110
|
}
|
|
93
111
|
|
|
112
|
+
@unsafe
|
|
94
113
|
let i32neg = x => WasmI32.sub(0n, x)
|
|
95
114
|
|
|
115
|
+
@unsafe
|
|
96
116
|
let i64not = x => WasmI64.xor(x, 0xffffffffffffffffN)
|
|
117
|
+
@unsafe
|
|
97
118
|
let i64neg = x => WasmI64.sub(0N, x)
|
|
98
119
|
|
|
99
120
|
// https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
|
121
|
+
@unsafe
|
|
100
122
|
let rec gcdHelp = (x, y) => {
|
|
101
123
|
if (WasmI64.eq(x, y) || WasmI64.eqz(x)) {
|
|
102
124
|
y
|
|
@@ -120,6 +142,7 @@ let rec gcdHelp = (x, y) => {
|
|
|
120
142
|
}
|
|
121
143
|
}
|
|
122
144
|
|
|
145
|
+
@unsafe
|
|
123
146
|
let gcd = (x, y) => {
|
|
124
147
|
// Algorithm above breaks on negatives, so
|
|
125
148
|
// we make sure that they are positive at the beginning
|
|
@@ -136,10 +159,12 @@ let gcd = (x, y) => {
|
|
|
136
159
|
gcdHelp(x, y)
|
|
137
160
|
}
|
|
138
161
|
|
|
162
|
+
@unsafe
|
|
139
163
|
let gcd32 = (x, y) => {
|
|
140
164
|
WasmI32.wrapI64(gcd(WasmI64.extendI32S(x), WasmI64.extendI32S(y)))
|
|
141
165
|
}
|
|
142
166
|
|
|
167
|
+
@unsafe
|
|
143
168
|
export let reducedInteger = x => {
|
|
144
169
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
145
170
|
newInt64(x)
|
|
@@ -153,29 +178,71 @@ export let reducedInteger = x => {
|
|
|
153
178
|
}
|
|
154
179
|
}
|
|
155
180
|
|
|
156
|
-
|
|
181
|
+
@unsafe
|
|
182
|
+
let reducedBigInteger = x => {
|
|
183
|
+
if (BI.canConvertToInt64(x)) {
|
|
184
|
+
// CONVENTION: We assume that this function is called in
|
|
185
|
+
// some sort of tail position, meaning that
|
|
186
|
+
// the original input is no longer used after
|
|
187
|
+
// this function returns.
|
|
188
|
+
let ret = reducedInteger(BI.toInt64(x))
|
|
189
|
+
Memory.decRef(x)
|
|
190
|
+
ret
|
|
191
|
+
} else {
|
|
192
|
+
x
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@unsafe
|
|
197
|
+
let reducedFractionBigInt = (x, y) => {
|
|
157
198
|
let mut x = x
|
|
158
199
|
let mut y = y
|
|
200
|
+
let mut needsDecref = false
|
|
159
201
|
|
|
160
|
-
if (
|
|
202
|
+
if (BI.isNegative(y)) {
|
|
161
203
|
// Normalization 1: Never do negative/negative
|
|
162
204
|
// Normalization 2: Never allow a negative denominator
|
|
163
|
-
|
|
164
|
-
|
|
205
|
+
needsDecref = true
|
|
206
|
+
x = BI.negate(x)
|
|
207
|
+
y = BI.negate(y)
|
|
165
208
|
}
|
|
166
|
-
if (
|
|
209
|
+
if (BI.eqz(y)) {
|
|
167
210
|
throw Exception.DivisionByZero
|
|
168
211
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
212
|
+
let quotremResult = Memory.malloc(8n)
|
|
213
|
+
BI.quotRem(x, y, quotremResult)
|
|
214
|
+
// Note that the contents of quotRem are malloc'ed
|
|
215
|
+
// inside of quotRem and need to be manually freed.
|
|
216
|
+
let q = WasmI32.load(quotremResult, 0n)
|
|
217
|
+
let r = WasmI32.load(quotremResult, 4n)
|
|
218
|
+
// free container used to store quotrem result
|
|
219
|
+
Memory.free(quotremResult)
|
|
220
|
+
let ret = if (BI.eqz(r)) {
|
|
221
|
+
// if remainder is zero, then return the quotient.
|
|
222
|
+
// We decRef the remainder, since we no longer need it
|
|
223
|
+
Memory.decRef(r)
|
|
224
|
+
reducedBigInteger(q)
|
|
172
225
|
} else {
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
226
|
+
// remainder is nonzero. we don't need the quotient and
|
|
227
|
+
// remainder anymore, so we discard them.
|
|
228
|
+
Memory.decRef(q)
|
|
229
|
+
Memory.decRef(r)
|
|
230
|
+
let factor = BI.gcd(x, y)
|
|
231
|
+
let xdiv = BI.div(x, factor)
|
|
232
|
+
let ydiv = BI.div(y, factor)
|
|
233
|
+
let ret = newRational(xdiv, ydiv)
|
|
234
|
+
Memory.decRef(factor)
|
|
235
|
+
ret
|
|
236
|
+
}
|
|
237
|
+
if (needsDecref) {
|
|
238
|
+
Memory.decRef(x)
|
|
239
|
+
Memory.decRef(y)
|
|
240
|
+
void
|
|
176
241
|
}
|
|
242
|
+
ret
|
|
177
243
|
}
|
|
178
244
|
|
|
245
|
+
@unsafe
|
|
179
246
|
let reducedFraction64 = (x, y) => {
|
|
180
247
|
let mut x = x
|
|
181
248
|
let mut y = y
|
|
@@ -193,28 +260,10 @@ let reducedFraction64 = (x, y) => {
|
|
|
193
260
|
reducedInteger(WasmI64.divS(x, y))
|
|
194
261
|
} else {
|
|
195
262
|
let factor = gcd(x, y)
|
|
196
|
-
let xdiv =
|
|
197
|
-
let ydiv =
|
|
198
|
-
newRational(xdiv, ydiv)
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
let safeI32Multiply = (x, y) => {
|
|
203
|
-
let prod = WasmI64.mul(WasmI64.extendI32S(x), WasmI64.extendI32S(y))
|
|
204
|
-
if (WasmI64.gtS(prod, _I32_MAX) || WasmI64.ltS(prod, _I32_MIN)) {
|
|
205
|
-
throw Exception.Overflow
|
|
206
|
-
}
|
|
207
|
-
WasmI32.wrapI64(prod)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
let safeI64Multiply = (x, y) => {
|
|
211
|
-
let prod = WasmI64.mul(x, y)
|
|
212
|
-
if (WasmI64.ne(x, 0N)) {
|
|
213
|
-
if (WasmI64.ne(WasmI64.divS(prod, x), y)) {
|
|
214
|
-
throw Exception.Overflow
|
|
215
|
-
}
|
|
263
|
+
let xdiv = WasmI64.divS(x, factor)
|
|
264
|
+
let ydiv = WasmI64.divS(y, factor)
|
|
265
|
+
newRational(BI.makeWrappedInt64(xdiv), BI.makeWrappedInt64(ydiv))
|
|
216
266
|
}
|
|
217
|
-
prod
|
|
218
267
|
}
|
|
219
268
|
|
|
220
269
|
// Accessor functions
|
|
@@ -240,34 +289,42 @@ let safeI64Multiply = (x, y) => {
|
|
|
240
289
|
* [numerator, denominator]
|
|
241
290
|
*/
|
|
242
291
|
|
|
292
|
+
@unsafe
|
|
243
293
|
export let boxedNumberTag = xptr => {
|
|
244
294
|
WasmI32.load(xptr, 4n)
|
|
245
295
|
}
|
|
246
296
|
|
|
297
|
+
@unsafe
|
|
247
298
|
export let boxedInt32Number = xptr => {
|
|
248
299
|
WasmI32.load(xptr, 8n)
|
|
249
300
|
}
|
|
250
301
|
|
|
302
|
+
@unsafe
|
|
251
303
|
export let boxedInt64Number = xptr => {
|
|
252
304
|
WasmI64.load(xptr, 8n)
|
|
253
305
|
}
|
|
254
306
|
|
|
307
|
+
@unsafe
|
|
255
308
|
export let boxedFloat32Number = xptr => {
|
|
256
309
|
WasmF32.load(xptr, 8n)
|
|
257
310
|
}
|
|
258
311
|
|
|
312
|
+
@unsafe
|
|
259
313
|
export let boxedFloat64Number = xptr => {
|
|
260
314
|
WasmF64.load(xptr, 8n)
|
|
261
315
|
}
|
|
262
316
|
|
|
317
|
+
@unsafe
|
|
263
318
|
export let boxedRationalNumerator = xptr => {
|
|
264
319
|
WasmI32.load(xptr, 8n)
|
|
265
320
|
}
|
|
266
321
|
|
|
322
|
+
@unsafe
|
|
267
323
|
export let boxedRationalDenominator = xptr => {
|
|
268
324
|
WasmI32.load(xptr, 12n)
|
|
269
325
|
}
|
|
270
326
|
|
|
327
|
+
@unsafe
|
|
271
328
|
export let coerceNumberToWasmF32 = (x: Number) => {
|
|
272
329
|
let x = WasmI32.fromGrain(x)
|
|
273
330
|
if (isSimpleNumber(x)) {
|
|
@@ -281,10 +338,13 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
281
338
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
282
339
|
WasmF32.convertI64S(boxedInt64Number(x))
|
|
283
340
|
},
|
|
341
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
342
|
+
BI.toFloat32(x)
|
|
343
|
+
},
|
|
284
344
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
285
345
|
WasmF32.div(
|
|
286
|
-
|
|
287
|
-
|
|
346
|
+
BI.toFloat32(boxedRationalNumerator(x)),
|
|
347
|
+
BI.toFloat32(boxedRationalDenominator(x))
|
|
288
348
|
)
|
|
289
349
|
},
|
|
290
350
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
@@ -306,6 +366,7 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
306
366
|
}
|
|
307
367
|
}
|
|
308
368
|
|
|
369
|
+
@unsafe
|
|
309
370
|
export let coerceNumberToWasmF64 = (x: Number) => {
|
|
310
371
|
let x = WasmI32.fromGrain(x)
|
|
311
372
|
if (isSimpleNumber(x)) {
|
|
@@ -319,10 +380,13 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
319
380
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
320
381
|
WasmF64.convertI64S(boxedInt64Number(x))
|
|
321
382
|
},
|
|
383
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
384
|
+
BI.toFloat64(x)
|
|
385
|
+
},
|
|
322
386
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
323
387
|
WasmF64.div(
|
|
324
|
-
|
|
325
|
-
|
|
388
|
+
BI.toFloat64(boxedRationalNumerator(x)),
|
|
389
|
+
BI.toFloat64(boxedRationalDenominator(x))
|
|
326
390
|
)
|
|
327
391
|
},
|
|
328
392
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
@@ -338,6 +402,7 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
338
402
|
}
|
|
339
403
|
}
|
|
340
404
|
|
|
405
|
+
@unsafe
|
|
341
406
|
export let coerceNumberToWasmI64 = (x: Number) => {
|
|
342
407
|
let x = WasmI32.fromGrain(x)
|
|
343
408
|
if (isSimpleNumber(x)) {
|
|
@@ -351,6 +416,9 @@ export let coerceNumberToWasmI64 = (x: Number) => {
|
|
|
351
416
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
352
417
|
boxedInt64Number(x)
|
|
353
418
|
},
|
|
419
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
420
|
+
BI.toInt64(x)
|
|
421
|
+
},
|
|
354
422
|
_ => {
|
|
355
423
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
356
424
|
throw Exception.NumberNotIntlike
|
|
@@ -359,6 +427,7 @@ export let coerceNumberToWasmI64 = (x: Number) => {
|
|
|
359
427
|
}
|
|
360
428
|
}
|
|
361
429
|
|
|
430
|
+
@unsafe
|
|
362
431
|
export let coerceNumberToWasmI32 = (x: Number) => {
|
|
363
432
|
let x = WasmI32.fromGrain(x)
|
|
364
433
|
if (isSimpleNumber(x)) {
|
|
@@ -376,6 +445,35 @@ export let coerceNumberToWasmI32 = (x: Number) => {
|
|
|
376
445
|
}
|
|
377
446
|
WasmI32.wrapI64(int64)
|
|
378
447
|
},
|
|
448
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
449
|
+
BI.toInt32(x)
|
|
450
|
+
},
|
|
451
|
+
_ => {
|
|
452
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
453
|
+
throw Exception.NumberNotIntlike
|
|
454
|
+
},
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
@unsafe
|
|
460
|
+
export let coerceNumberToBigInt = (x: Number) => {
|
|
461
|
+
let x = WasmI32.fromGrain(x)
|
|
462
|
+
if (isSimpleNumber(x)) {
|
|
463
|
+
BI.makeWrappedInt32(untagSimple(x))
|
|
464
|
+
} else {
|
|
465
|
+
let xtag = boxedNumberTag(x)
|
|
466
|
+
match (xtag) {
|
|
467
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
468
|
+
BI.makeWrappedInt32(boxedInt32Number(x))
|
|
469
|
+
},
|
|
470
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
471
|
+
BI.makeWrappedInt64(boxedInt64Number(x))
|
|
472
|
+
},
|
|
473
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
474
|
+
Memory.incRef(x)
|
|
475
|
+
x
|
|
476
|
+
},
|
|
379
477
|
_ => {
|
|
380
478
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
381
479
|
throw Exception.NumberNotIntlike
|
|
@@ -384,19 +482,23 @@ export let coerceNumberToWasmI32 = (x: Number) => {
|
|
|
384
482
|
}
|
|
385
483
|
}
|
|
386
484
|
|
|
485
|
+
@unsafe
|
|
387
486
|
let isIntegerF32 = value => {
|
|
388
487
|
WasmF32.eq(value, WasmF32.trunc(value))
|
|
389
488
|
}
|
|
390
489
|
|
|
490
|
+
@unsafe
|
|
391
491
|
let isIntegerF64 = value => {
|
|
392
492
|
WasmF64.eq(value, WasmF64.trunc(value))
|
|
393
493
|
}
|
|
394
494
|
|
|
495
|
+
@unsafe
|
|
395
496
|
let isSafeIntegerF32 = value => {
|
|
396
497
|
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
397
498
|
WasmF32.eq(WasmF32.trunc(value), value)
|
|
398
499
|
}
|
|
399
500
|
|
|
501
|
+
@unsafe
|
|
400
502
|
let isSafeIntegerF64 = value => {
|
|
401
503
|
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
402
504
|
WasmF64.eq(WasmF64.trunc(value), value)
|
|
@@ -411,6 +513,7 @@ let isSafeIntegerF64 = value => {
|
|
|
411
513
|
* export them!
|
|
412
514
|
*/
|
|
413
515
|
|
|
516
|
+
@unsafe
|
|
414
517
|
let numberEqualSimpleHelp = (x, y) => {
|
|
415
518
|
// PRECONDITION: x is a "simple" number (value tag is 0) and x !== y and isNumber(y)
|
|
416
519
|
if (isSimpleNumber(y)) {
|
|
@@ -428,6 +531,9 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
428
531
|
let yBoxedVal = boxedInt64Number(y)
|
|
429
532
|
WasmI64.eq(WasmI64.extendI32S(xval), yBoxedVal)
|
|
430
533
|
},
|
|
534
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
535
|
+
WasmI32.eqz(BI.cmpI64(y, WasmI64.extendI32S(xval)))
|
|
536
|
+
},
|
|
431
537
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
432
538
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
433
539
|
false
|
|
@@ -449,6 +555,7 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
449
555
|
}
|
|
450
556
|
}
|
|
451
557
|
|
|
558
|
+
@unsafe
|
|
452
559
|
let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
453
560
|
// PRECONDITION: x !== y and isNumber(y)
|
|
454
561
|
// Basic number:
|
|
@@ -466,6 +573,9 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
466
573
|
let yBoxedVal = boxedInt64Number(y)
|
|
467
574
|
WasmI64.eq(xBoxedVal, yBoxedVal)
|
|
468
575
|
},
|
|
576
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
577
|
+
WasmI32.eqz(BI.cmpI64(y, xBoxedVal))
|
|
578
|
+
},
|
|
469
579
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
470
580
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
471
581
|
false
|
|
@@ -487,11 +597,13 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
487
597
|
}
|
|
488
598
|
}
|
|
489
599
|
|
|
600
|
+
@unsafe
|
|
490
601
|
let numberEqualInt32Help = (xBoxedVal, y) => {
|
|
491
602
|
// We can just pretend it's 64-bit for the equality check
|
|
492
603
|
numberEqualInt64Help(WasmI64.extendI32S(xBoxedVal), y)
|
|
493
604
|
}
|
|
494
605
|
|
|
606
|
+
@unsafe
|
|
495
607
|
let numberEqualRationalHelp = (xptr, y) => {
|
|
496
608
|
// PRECONDITION: x is rational and x !== y and isNumber(y)
|
|
497
609
|
// Basic number: (we know it's not equal, since we never store ints as rationals)
|
|
@@ -509,17 +621,19 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
509
621
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
510
622
|
false
|
|
511
623
|
},
|
|
624
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
625
|
+
false
|
|
626
|
+
},
|
|
512
627
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
513
628
|
let yNumerator = boxedRationalNumerator(y)
|
|
514
629
|
let yDenominator = boxedRationalDenominator(y)
|
|
515
|
-
|
|
516
|
-
WasmI32.eq(xDenominator, yDenominator)
|
|
630
|
+
BI.eq(xNumerator, yNumerator) && BI.eq(xDenominator, yDenominator)
|
|
517
631
|
},
|
|
518
632
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
519
633
|
let yBoxedVal = boxedFloat32Number(y)
|
|
520
634
|
let xAsFloat = WasmF32.div(
|
|
521
|
-
|
|
522
|
-
|
|
635
|
+
BI.toFloat32(xNumerator),
|
|
636
|
+
BI.toFloat32(xDenominator)
|
|
523
637
|
)
|
|
524
638
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
525
639
|
WasmF32.eq(xAsFloat, yBoxedVal)
|
|
@@ -527,8 +641,8 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
527
641
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
528
642
|
let yBoxedVal = boxedFloat64Number(y)
|
|
529
643
|
let xAsFloat = WasmF64.div(
|
|
530
|
-
|
|
531
|
-
|
|
644
|
+
BI.toFloat64(xNumerator),
|
|
645
|
+
BI.toFloat64(xDenominator)
|
|
532
646
|
)
|
|
533
647
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
534
648
|
WasmF64.eq(xAsFloat, yBoxedVal)
|
|
@@ -540,6 +654,7 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
540
654
|
}
|
|
541
655
|
}
|
|
542
656
|
|
|
657
|
+
@unsafe
|
|
543
658
|
let numberEqualFloat64Help = (x, y) => {
|
|
544
659
|
let xIsInteger = isIntegerF64(x)
|
|
545
660
|
// Basic number:
|
|
@@ -557,12 +672,15 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
557
672
|
let yBoxedVal = boxedInt64Number(y)
|
|
558
673
|
isSafeIntegerF64(x) && WasmF64.eq(x, WasmF64.convertI64S(yBoxedVal))
|
|
559
674
|
},
|
|
675
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
676
|
+
WasmI32.eqz(BI.cmpF64(y, x))
|
|
677
|
+
},
|
|
560
678
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
561
679
|
let yNumerator = boxedRationalNumerator(y)
|
|
562
680
|
let yDenominator = boxedRationalDenominator(y)
|
|
563
681
|
let yAsFloat = WasmF64.div(
|
|
564
|
-
|
|
565
|
-
|
|
682
|
+
BI.toFloat64(yNumerator),
|
|
683
|
+
BI.toFloat64(yDenominator)
|
|
566
684
|
)
|
|
567
685
|
WasmF64.eq(x, yAsFloat)
|
|
568
686
|
},
|
|
@@ -583,6 +701,7 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
583
701
|
}
|
|
584
702
|
}
|
|
585
703
|
|
|
704
|
+
@unsafe
|
|
586
705
|
let numberEqualFloat32Help = (x, y) => {
|
|
587
706
|
let xIsInteger = isIntegerF32(x)
|
|
588
707
|
// Basic number:
|
|
@@ -603,6 +722,45 @@ let numberEqualFloat32Help = (x, y) => {
|
|
|
603
722
|
}
|
|
604
723
|
}
|
|
605
724
|
|
|
725
|
+
@unsafe
|
|
726
|
+
let numberEqualBigIntHelp = (x, y) => {
|
|
727
|
+
if (isSimpleNumber(y)) {
|
|
728
|
+
WasmI32.eqz(BI.cmpI64(x, WasmI64.extendI32S(untagSimple(y))))
|
|
729
|
+
} else {
|
|
730
|
+
// Boxed number
|
|
731
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
732
|
+
match (yBoxedNumberTag) {
|
|
733
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
734
|
+
let yBoxedVal = boxedInt32Number(y)
|
|
735
|
+
WasmI32.eqz(BI.cmpI64(x, WasmI64.extendI32S(yBoxedVal)))
|
|
736
|
+
},
|
|
737
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
738
|
+
let yBoxedVal = boxedInt64Number(y)
|
|
739
|
+
WasmI32.eqz(BI.cmpI64(x, yBoxedVal))
|
|
740
|
+
},
|
|
741
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
742
|
+
BI.eq(x, y)
|
|
743
|
+
},
|
|
744
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
745
|
+
// Rationals are reduced, so it must be unequal
|
|
746
|
+
false
|
|
747
|
+
},
|
|
748
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
749
|
+
let yBoxedVal = boxedFloat32Number(y)
|
|
750
|
+
WasmI32.eqz(BI.cmpF32(x, yBoxedVal))
|
|
751
|
+
},
|
|
752
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
753
|
+
let yBoxedVal = boxedFloat64Number(y)
|
|
754
|
+
WasmI32.eqz(BI.cmpF64(x, yBoxedVal))
|
|
755
|
+
},
|
|
756
|
+
_ => {
|
|
757
|
+
throw UnknownNumberTag
|
|
758
|
+
},
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
@unsafe
|
|
606
764
|
export let numberEqual = (x, y) => {
|
|
607
765
|
if (isSimpleNumber(x)) {
|
|
608
766
|
// Short circuit if non-pointer value is the same
|
|
@@ -628,6 +786,9 @@ export let numberEqual = (x, y) => {
|
|
|
628
786
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
629
787
|
numberEqualFloat64Help(boxedFloat64Number(x), y)
|
|
630
788
|
},
|
|
789
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
790
|
+
numberEqualBigIntHelp(x, y)
|
|
791
|
+
},
|
|
631
792
|
_ => {
|
|
632
793
|
throw UnknownNumberTag
|
|
633
794
|
},
|
|
@@ -640,6 +801,7 @@ export let numberEqual = (x, y) => {
|
|
|
640
801
|
* (same schema as equal())
|
|
641
802
|
*/
|
|
642
803
|
|
|
804
|
+
@unsafe
|
|
643
805
|
let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
644
806
|
// PRECONDITION: x is a "simple" number (value tag is 0) and isNumber(y)
|
|
645
807
|
if (isSimpleNumber(y)) {
|
|
@@ -667,27 +829,44 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
667
829
|
let xval64 = WasmI64.extendI32S(xval)
|
|
668
830
|
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
669
831
|
else WasmI64.add(xval64, yBoxedVal)
|
|
670
|
-
if (
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
832
|
+
if (
|
|
833
|
+
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
834
|
+
WasmI64.ltS(yBoxedVal, 0N) && WasmI64.gtS(result, xval64)
|
|
835
|
+
) {
|
|
836
|
+
// Overflow. Promote to BigInt
|
|
837
|
+
let xBig = BI.makeWrappedInt32(xval)
|
|
838
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
839
|
+
let res = if (isSub) {
|
|
840
|
+
BI.sub(xBig, yBig)
|
|
841
|
+
} else {
|
|
842
|
+
BI.add(xBig, yBig)
|
|
843
|
+
}
|
|
844
|
+
Memory.decRef(xBig)
|
|
845
|
+
Memory.decRef(yBig)
|
|
846
|
+
reducedBigInteger(res)
|
|
674
847
|
} else {
|
|
675
848
|
reducedInteger(result)
|
|
676
849
|
}
|
|
677
850
|
},
|
|
851
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
852
|
+
// Promote x to bigint and do operation
|
|
853
|
+
let xBig = BI.makeWrappedInt32(xval)
|
|
854
|
+
let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
|
|
855
|
+
Memory.decRef(xBig)
|
|
856
|
+
reducedBigInteger(result)
|
|
857
|
+
},
|
|
678
858
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
679
|
-
let
|
|
680
|
-
let
|
|
681
|
-
let
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
)
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
reducedFraction64(result, yDenominator)
|
|
859
|
+
let xBig = BI.makeWrappedInt32(xval)
|
|
860
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
861
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
862
|
+
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
863
|
+
Memory.decRef(xBig)
|
|
864
|
+
let result = if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
865
|
+
else BI.add(expandedXNumerator, yNumerator)
|
|
866
|
+
let ret = reducedFractionBigInt(result, yDenominator)
|
|
867
|
+
Memory.decRef(expandedXNumerator)
|
|
868
|
+
Memory.decRef(result)
|
|
869
|
+
ret
|
|
691
870
|
},
|
|
692
871
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
693
872
|
let yBoxedVal = boxedFloat32Number(y)
|
|
@@ -711,16 +890,29 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
711
890
|
}
|
|
712
891
|
}
|
|
713
892
|
|
|
893
|
+
@unsafe
|
|
714
894
|
let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
715
895
|
if (isSimpleNumber(y)) {
|
|
716
896
|
let yval = WasmI64.extendI32S(untagSimple(y))
|
|
717
897
|
let result = if (isSub) WasmI64.sub(xval, yval) else WasmI64.add(xval, yval)
|
|
718
|
-
if (
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
898
|
+
if (
|
|
899
|
+
WasmI64.geS(yval, 0N) && WasmI64.ltS(result, xval) ||
|
|
900
|
+
WasmI64.ltS(yval, 0N) && WasmI64.gtS(result, xval)
|
|
901
|
+
) {
|
|
902
|
+
// Overflow. Promote to BigInt
|
|
903
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
904
|
+
let yBig = BI.makeWrappedInt64(yval)
|
|
905
|
+
let res = if (isSub) {
|
|
906
|
+
BI.sub(xBig, yBig)
|
|
907
|
+
} else {
|
|
908
|
+
BI.add(xBig, yBig)
|
|
909
|
+
}
|
|
910
|
+
Memory.decRef(xBig)
|
|
911
|
+
Memory.decRef(yBig)
|
|
912
|
+
reducedBigInteger(res)
|
|
913
|
+
} else {
|
|
914
|
+
reducedInteger(result)
|
|
722
915
|
}
|
|
723
|
-
reducedInteger(result)
|
|
724
916
|
} else {
|
|
725
917
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
726
918
|
match (yBoxedNumberTag) {
|
|
@@ -735,31 +927,51 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
735
927
|
let xval64 = xval
|
|
736
928
|
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
737
929
|
else WasmI64.add(xval64, yBoxedVal)
|
|
738
|
-
if (
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
930
|
+
if (
|
|
931
|
+
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
932
|
+
WasmI64.ltS(yBoxedVal, 0N) && WasmI64.gtS(result, xval64)
|
|
933
|
+
) {
|
|
934
|
+
// Overflow. Promote to BigInt
|
|
935
|
+
let xBig = BI.makeWrappedInt64(xval64)
|
|
936
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
937
|
+
let res = if (isSub) {
|
|
938
|
+
BI.sub(xBig, yBig)
|
|
939
|
+
} else {
|
|
940
|
+
BI.add(xBig, yBig)
|
|
941
|
+
}
|
|
942
|
+
Memory.decRef(xBig)
|
|
943
|
+
Memory.decRef(yBig)
|
|
944
|
+
reducedBigInteger(res)
|
|
742
945
|
} else {
|
|
743
946
|
reducedInteger(result)
|
|
744
947
|
}
|
|
745
948
|
},
|
|
949
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
950
|
+
// Promote x to bigint and do operation
|
|
951
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
952
|
+
let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
|
|
953
|
+
Memory.decRef(xBig)
|
|
954
|
+
reducedBigInteger(result)
|
|
955
|
+
},
|
|
746
956
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
747
|
-
let
|
|
748
|
-
let
|
|
749
|
-
let
|
|
750
|
-
let
|
|
751
|
-
|
|
752
|
-
if (
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
957
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
958
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
959
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
960
|
+
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
961
|
+
Memory.decRef(xBig)
|
|
962
|
+
let result = if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
963
|
+
else BI.add(expandedXNumerator, yNumerator)
|
|
964
|
+
let ret = reducedFractionBigInt(result, yDenominator)
|
|
965
|
+
Memory.decRef(expandedXNumerator)
|
|
966
|
+
Memory.decRef(result)
|
|
967
|
+
ret
|
|
756
968
|
},
|
|
757
969
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
758
970
|
let xval = WasmF32.convertI64S(xval)
|
|
759
971
|
let yBoxedVal = boxedFloat32Number(y)
|
|
760
972
|
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
761
973
|
else WasmF32.add(xval, yBoxedVal)
|
|
762
|
-
// TODO
|
|
974
|
+
// TODO(#304): this isn't safe enough
|
|
763
975
|
newFloat32(result)
|
|
764
976
|
},
|
|
765
977
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
@@ -776,6 +988,7 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
776
988
|
}
|
|
777
989
|
}
|
|
778
990
|
|
|
991
|
+
@unsafe
|
|
779
992
|
let numberAddSubFloat32Help = (xval, y, isSub) => {
|
|
780
993
|
if (
|
|
781
994
|
!isSimpleNumber(y) &&
|
|
@@ -787,85 +1000,230 @@ let numberAddSubFloat32Help = (xval, y, isSub) => {
|
|
|
787
1000
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
788
1001
|
newFloat64(result)
|
|
789
1002
|
} else {
|
|
1003
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1004
|
+
Memory.incRef(y)
|
|
790
1005
|
let yval = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
791
1006
|
let result = if (isSub) WasmF32.sub(xval, yval) else WasmF32.add(xval, yval)
|
|
792
1007
|
newFloat32(result)
|
|
793
1008
|
}
|
|
794
1009
|
}
|
|
795
1010
|
|
|
1011
|
+
@unsafe
|
|
796
1012
|
let numberAddSubFloat64Help = (xval, y, isSub) => {
|
|
1013
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1014
|
+
Memory.incRef(y)
|
|
797
1015
|
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
798
1016
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
799
1017
|
newFloat64(result)
|
|
800
1018
|
}
|
|
801
1019
|
|
|
1020
|
+
@unsafe
|
|
802
1021
|
let numberAddSubInt32Help = (xval, y, isSub) => {
|
|
803
1022
|
numberAddSubInt64Help(WasmI64.extendI32S(xval), y, isSub)
|
|
804
1023
|
}
|
|
805
1024
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
1025
|
+
@unsafe
|
|
1026
|
+
let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
1027
|
+
if (isSimpleNumber(y)) {
|
|
1028
|
+
let yval = WasmI64.extendI32S(untagSimple(y))
|
|
1029
|
+
let yBig = BI.makeWrappedInt64(yval)
|
|
1030
|
+
let res = if (isSub) {
|
|
1031
|
+
BI.sub(x, yBig)
|
|
1032
|
+
} else {
|
|
1033
|
+
BI.add(x, yBig)
|
|
1034
|
+
}
|
|
1035
|
+
Memory.decRef(yBig)
|
|
1036
|
+
reducedBigInteger(res)
|
|
809
1037
|
} else {
|
|
810
|
-
let
|
|
811
|
-
match (
|
|
1038
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1039
|
+
match (yBoxedNumberTag) {
|
|
812
1040
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
813
|
-
|
|
1041
|
+
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1042
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1043
|
+
let res = if (isSub) {
|
|
1044
|
+
BI.sub(x, yBig)
|
|
1045
|
+
} else {
|
|
1046
|
+
BI.add(x, yBig)
|
|
1047
|
+
}
|
|
1048
|
+
Memory.decRef(yBig)
|
|
1049
|
+
reducedBigInteger(res)
|
|
814
1050
|
},
|
|
815
1051
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
816
|
-
|
|
1052
|
+
let yBoxedVal = boxedInt64Number(y)
|
|
1053
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1054
|
+
let res = if (isSub) {
|
|
1055
|
+
BI.sub(x, yBig)
|
|
1056
|
+
} else {
|
|
1057
|
+
BI.add(x, yBig)
|
|
1058
|
+
}
|
|
1059
|
+
Memory.decRef(yBig)
|
|
1060
|
+
reducedBigInteger(res)
|
|
1061
|
+
},
|
|
1062
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1063
|
+
let res = if (isSub) {
|
|
1064
|
+
BI.sub(x, y)
|
|
1065
|
+
} else {
|
|
1066
|
+
BI.add(x, y)
|
|
1067
|
+
}
|
|
1068
|
+
reducedBigInteger(res)
|
|
817
1069
|
},
|
|
818
1070
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
819
|
-
|
|
1071
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1072
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1073
|
+
let expandedXNumerator = BI.mul(x, yDenominator)
|
|
1074
|
+
let result = if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
1075
|
+
else BI.add(expandedXNumerator, yNumerator)
|
|
1076
|
+
Memory.decRef(expandedXNumerator)
|
|
1077
|
+
let ret = reducedFractionBigInt(result, yDenominator)
|
|
1078
|
+
Memory.decRef(result)
|
|
1079
|
+
ret
|
|
820
1080
|
},
|
|
821
1081
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
822
|
-
|
|
1082
|
+
let xval = BI.toFloat32(x)
|
|
1083
|
+
let yBoxedVal = boxedFloat32Number(y)
|
|
1084
|
+
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
1085
|
+
else WasmF32.add(xval, yBoxedVal)
|
|
1086
|
+
// TODO: (#304) this isn't safe enough
|
|
1087
|
+
newFloat32(result)
|
|
823
1088
|
},
|
|
824
1089
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
825
|
-
|
|
1090
|
+
let xval = BI.toFloat64(x)
|
|
1091
|
+
let yBoxedVal = boxedFloat64Number(y)
|
|
1092
|
+
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1093
|
+
else WasmF64.add(xval, yBoxedVal)
|
|
1094
|
+
newFloat64(result)
|
|
826
1095
|
},
|
|
827
1096
|
_ => {
|
|
828
1097
|
throw UnknownNumberTag
|
|
829
1098
|
},
|
|
830
1099
|
}
|
|
831
1100
|
}
|
|
832
|
-
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
@unsafe
|
|
1104
|
+
let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
1105
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1106
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
833
1107
|
if (isSimpleNumber(y)) {
|
|
834
|
-
|
|
1108
|
+
let yval = untagSimple(y)
|
|
1109
|
+
let yBig = BI.makeWrappedInt32(yval)
|
|
1110
|
+
let expandedYNumerator = BI.mul(xDenominator, yBig)
|
|
1111
|
+
let result = if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1112
|
+
else BI.add(xNumerator, expandedYNumerator)
|
|
1113
|
+
Memory.decRef(expandedYNumerator)
|
|
1114
|
+
Memory.decRef(yBig)
|
|
1115
|
+
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1116
|
+
Memory.decRef(result)
|
|
1117
|
+
ret
|
|
835
1118
|
} else {
|
|
836
1119
|
let ytag = boxedNumberTag(y)
|
|
837
1120
|
match (ytag) {
|
|
838
1121
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
839
1122
|
// The one case we don't delegate is rational +/- rational
|
|
840
|
-
let xNumerator =
|
|
841
|
-
let xDenominator =
|
|
842
|
-
let yNumerator =
|
|
843
|
-
let yDenominator =
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1123
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1124
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1125
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1126
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1127
|
+
if (BI.eq(xDenominator, yDenominator)) {
|
|
1128
|
+
let newNumerator = if (isSub) BI.sub(xNumerator, yNumerator)
|
|
1129
|
+
else BI.add(xNumerator, yNumerator)
|
|
1130
|
+
let ret = reducedFractionBigInt(newNumerator, xDenominator)
|
|
1131
|
+
Memory.decRef(newNumerator)
|
|
1132
|
+
ret
|
|
849
1133
|
} else {
|
|
850
|
-
let numerator1 =
|
|
851
|
-
let numerator2 =
|
|
852
|
-
let numerator = if (isSub)
|
|
853
|
-
else
|
|
854
|
-
let denominator =
|
|
855
|
-
|
|
1134
|
+
let numerator1 = BI.mul(xNumerator, yDenominator)
|
|
1135
|
+
let numerator2 = BI.mul(yNumerator, xDenominator)
|
|
1136
|
+
let numerator = if (isSub) BI.sub(numerator1, numerator2)
|
|
1137
|
+
else BI.add(numerator1, numerator2)
|
|
1138
|
+
let denominator = BI.mul(xDenominator, yDenominator)
|
|
1139
|
+
let ret = reducedFractionBigInt(numerator, denominator)
|
|
1140
|
+
Memory.decRef(numerator1)
|
|
1141
|
+
Memory.decRef(numerator2)
|
|
1142
|
+
Memory.decRef(numerator)
|
|
1143
|
+
ret
|
|
856
1144
|
}
|
|
857
1145
|
},
|
|
858
1146
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
859
|
-
|
|
1147
|
+
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1148
|
+
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1149
|
+
Memory.decRef(yBig)
|
|
1150
|
+
let result = if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1151
|
+
else BI.add(xNumerator, expandedYNumerator)
|
|
1152
|
+
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1153
|
+
Memory.decRef(expandedYNumerator)
|
|
1154
|
+
Memory.decRef(result)
|
|
1155
|
+
ret
|
|
1156
|
+
},
|
|
1157
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1158
|
+
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1159
|
+
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1160
|
+
Memory.decRef(yBig)
|
|
1161
|
+
let result = if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1162
|
+
else BI.add(xNumerator, expandedYNumerator)
|
|
1163
|
+
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1164
|
+
Memory.decRef(expandedYNumerator)
|
|
1165
|
+
Memory.decRef(result)
|
|
1166
|
+
ret
|
|
1167
|
+
},
|
|
1168
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1169
|
+
let expandedYNumerator = BI.mul(xDenominator, y)
|
|
1170
|
+
let result = if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1171
|
+
else BI.add(xNumerator, expandedYNumerator)
|
|
1172
|
+
Memory.decRef(expandedYNumerator)
|
|
1173
|
+
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1174
|
+
Memory.decRef(result)
|
|
1175
|
+
ret
|
|
1176
|
+
},
|
|
1177
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1178
|
+
let xval = WasmF32.div(
|
|
1179
|
+
BI.toFloat32(xNumerator),
|
|
1180
|
+
BI.toFloat32(xDenominator)
|
|
1181
|
+
)
|
|
1182
|
+
let result = if (isSub) WasmF32.sub(xval, boxedFloat32Number(y))
|
|
1183
|
+
else WasmF32.add(xval, boxedFloat32Number(y))
|
|
1184
|
+
newFloat32(result)
|
|
1185
|
+
},
|
|
1186
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1187
|
+
let xnumfloat = BI.toFloat64(xNumerator)
|
|
1188
|
+
let xdenfloat = BI.toFloat64(xDenominator)
|
|
1189
|
+
let xval = WasmF64.div(xnumfloat, xdenfloat)
|
|
1190
|
+
let yval = boxedFloat64Number(y)
|
|
1191
|
+
let result = if (isSub) WasmF64.sub(xval, yval)
|
|
1192
|
+
else WasmF64.add(xval, yval)
|
|
1193
|
+
let ret = newFloat64(result)
|
|
1194
|
+
ret
|
|
1195
|
+
},
|
|
1196
|
+
_ => {
|
|
1197
|
+
throw UnknownNumberTag
|
|
1198
|
+
},
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
@unsafe
|
|
1204
|
+
let numberAddSubHelp = (x, y, isSub) => {
|
|
1205
|
+
if (isSimpleNumber(x)) {
|
|
1206
|
+
numberAddSubSimpleHelp(x, y, isSub)
|
|
1207
|
+
} else {
|
|
1208
|
+
let xtag = boxedNumberTag(x)
|
|
1209
|
+
match (xtag) {
|
|
1210
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1211
|
+
numberAddSubInt32Help(boxedInt32Number(x), y, isSub)
|
|
860
1212
|
},
|
|
861
1213
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
862
|
-
|
|
1214
|
+
numberAddSubInt64Help(boxedInt64Number(x), y, isSub)
|
|
1215
|
+
},
|
|
1216
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1217
|
+
numberAddSubBigIntHelp(x, y, isSub)
|
|
1218
|
+
},
|
|
1219
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1220
|
+
numberAddSubRationalHelp(x, y, isSub)
|
|
863
1221
|
},
|
|
864
1222
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
865
|
-
|
|
1223
|
+
numberAddSubFloat32Help(boxedFloat32Number(x), y, isSub)
|
|
866
1224
|
},
|
|
867
1225
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
868
|
-
|
|
1226
|
+
numberAddSubFloat64Help(boxedFloat64Number(x), y, isSub)
|
|
869
1227
|
},
|
|
870
1228
|
_ => {
|
|
871
1229
|
throw UnknownNumberTag
|
|
@@ -874,10 +1232,12 @@ let rec numberAddSubHelp = (x, y, isSub) => {
|
|
|
874
1232
|
}
|
|
875
1233
|
}
|
|
876
1234
|
|
|
1235
|
+
@unsafe
|
|
877
1236
|
let numberAdd = (x, y) => {
|
|
878
1237
|
WasmI32.toGrain(numberAddSubHelp(x, y, false)): Number
|
|
879
1238
|
}
|
|
880
1239
|
|
|
1240
|
+
@unsafe
|
|
881
1241
|
let numberSub = (x, y) => {
|
|
882
1242
|
WasmI32.toGrain(numberAddSubHelp(x, y, true)): Number
|
|
883
1243
|
}
|
|
@@ -887,12 +1247,32 @@ let numberSub = (x, y) => {
|
|
|
887
1247
|
* (same schema as equal())
|
|
888
1248
|
*/
|
|
889
1249
|
|
|
1250
|
+
@unsafe
|
|
1251
|
+
let safeI64Multiply = (x, y) => {
|
|
1252
|
+
let prod = WasmI64.mul(x, y)
|
|
1253
|
+
if (WasmI64.ne(x, 0N)) {
|
|
1254
|
+
if (WasmI64.ne(WasmI64.divS(prod, x), y)) {
|
|
1255
|
+
let xBig = BI.makeWrappedInt64(x)
|
|
1256
|
+
let yBig = BI.makeWrappedInt64(y)
|
|
1257
|
+
let result = BI.mul(xBig, yBig)
|
|
1258
|
+
Memory.decRef(xBig)
|
|
1259
|
+
Memory.decRef(yBig)
|
|
1260
|
+
result
|
|
1261
|
+
} else {
|
|
1262
|
+
reducedInteger(prod)
|
|
1263
|
+
}
|
|
1264
|
+
} else {
|
|
1265
|
+
reducedInteger(prod)
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
@unsafe
|
|
890
1270
|
let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
891
1271
|
if (isSimpleNumber(y)) {
|
|
892
1272
|
if (isDivide) {
|
|
893
1273
|
reducedFraction64(xval, WasmI64.extendI32S(untagSimple(y)))
|
|
894
1274
|
} else {
|
|
895
|
-
|
|
1275
|
+
safeI64Multiply(xval, WasmI64.extendI32S(untagSimple(y)))
|
|
896
1276
|
}
|
|
897
1277
|
} else {
|
|
898
1278
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
@@ -902,7 +1282,7 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
902
1282
|
if (isDivide) {
|
|
903
1283
|
reducedFraction64(xval, yBoxedVal)
|
|
904
1284
|
} else {
|
|
905
|
-
|
|
1285
|
+
safeI64Multiply(xval, yBoxedVal)
|
|
906
1286
|
}
|
|
907
1287
|
},
|
|
908
1288
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
@@ -910,21 +1290,38 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
910
1290
|
if (isDivide) {
|
|
911
1291
|
reducedFraction64(xval, yBoxedVal)
|
|
912
1292
|
} else {
|
|
913
|
-
|
|
1293
|
+
safeI64Multiply(xval, yBoxedVal)
|
|
1294
|
+
}
|
|
1295
|
+
},
|
|
1296
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1297
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
1298
|
+
let ret = if (isDivide) {
|
|
1299
|
+
reducedFractionBigInt(xBig, y)
|
|
1300
|
+
} else {
|
|
1301
|
+
reducedBigInteger(BI.mul(xBig, y))
|
|
914
1302
|
}
|
|
1303
|
+
Memory.decRef(xBig)
|
|
1304
|
+
ret
|
|
915
1305
|
},
|
|
916
1306
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
917
|
-
let yNumerator =
|
|
918
|
-
let yDenominator =
|
|
919
|
-
|
|
1307
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1308
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1309
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
1310
|
+
let ret = if (isDivide) {
|
|
920
1311
|
// x / (a / b) == (x * b) / a
|
|
921
|
-
let numerator =
|
|
922
|
-
|
|
1312
|
+
let numerator = BI.mul(xBig, yDenominator)
|
|
1313
|
+
let ret = reducedFractionBigInt(numerator, yNumerator)
|
|
1314
|
+
Memory.decRef(numerator)
|
|
1315
|
+
ret
|
|
923
1316
|
} else {
|
|
924
1317
|
// x * (a / b) == (x * a) / b
|
|
925
|
-
let numerator =
|
|
926
|
-
|
|
1318
|
+
let numerator = BI.mul(xBig, yNumerator)
|
|
1319
|
+
let ret = reducedFractionBigInt(numerator, yDenominator)
|
|
1320
|
+
Memory.decRef(numerator)
|
|
1321
|
+
ret
|
|
927
1322
|
}
|
|
1323
|
+
Memory.decRef(xBig)
|
|
1324
|
+
ret
|
|
928
1325
|
},
|
|
929
1326
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
930
1327
|
let xval = WasmF32.convertI64S(xval)
|
|
@@ -952,88 +1349,198 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
952
1349
|
}
|
|
953
1350
|
}
|
|
954
1351
|
|
|
1352
|
+
@unsafe
|
|
1353
|
+
let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
1354
|
+
if (isSimpleNumber(y)) {
|
|
1355
|
+
let yBig = BI.makeWrappedInt32(untagSimple(y))
|
|
1356
|
+
let ret = if (isDivide) {
|
|
1357
|
+
reducedFractionBigInt(x, yBig)
|
|
1358
|
+
} else {
|
|
1359
|
+
reducedBigInteger(BI.mul(x, yBig))
|
|
1360
|
+
}
|
|
1361
|
+
Memory.decRef(yBig)
|
|
1362
|
+
ret
|
|
1363
|
+
} else {
|
|
1364
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1365
|
+
match (yBoxedNumberTag) {
|
|
1366
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1367
|
+
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1368
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1369
|
+
let ret = if (isDivide) {
|
|
1370
|
+
reducedFractionBigInt(x, yBig)
|
|
1371
|
+
} else {
|
|
1372
|
+
reducedBigInteger(BI.mul(x, yBig))
|
|
1373
|
+
}
|
|
1374
|
+
Memory.decRef(yBig)
|
|
1375
|
+
ret
|
|
1376
|
+
},
|
|
1377
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1378
|
+
let yBoxedVal = boxedInt64Number(y)
|
|
1379
|
+
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1380
|
+
let ret = if (isDivide) {
|
|
1381
|
+
reducedFractionBigInt(x, yBig)
|
|
1382
|
+
} else {
|
|
1383
|
+
reducedBigInteger(BI.mul(x, yBig))
|
|
1384
|
+
}
|
|
1385
|
+
Memory.decRef(yBig)
|
|
1386
|
+
ret
|
|
1387
|
+
},
|
|
1388
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1389
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1390
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1391
|
+
if (isDivide) {
|
|
1392
|
+
// x / (a / b) == (x * b) / a
|
|
1393
|
+
let numerator = BI.mul(x, yDenominator)
|
|
1394
|
+
let ret = reducedFractionBigInt(numerator, yNumerator)
|
|
1395
|
+
Memory.decRef(numerator)
|
|
1396
|
+
ret
|
|
1397
|
+
} else {
|
|
1398
|
+
// x * (a / b) == (x * a) / b
|
|
1399
|
+
let numerator = BI.mul(x, yNumerator)
|
|
1400
|
+
let ret = reducedFractionBigInt(numerator, yDenominator)
|
|
1401
|
+
Memory.decRef(numerator)
|
|
1402
|
+
ret
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1406
|
+
// We make the decision to always promote to f64 here, since
|
|
1407
|
+
// we can only fit rather small bigints (<4 limbs) into an F32
|
|
1408
|
+
let xval = BI.toFloat64(x)
|
|
1409
|
+
let yBoxedVal = WasmF64.promoteF32(boxedFloat32Number(y))
|
|
1410
|
+
// TODO: (#304) is this safe?
|
|
1411
|
+
if (isDivide) {
|
|
1412
|
+
newFloat64(WasmF64.div(xval, yBoxedVal))
|
|
1413
|
+
} else {
|
|
1414
|
+
newFloat64(WasmF64.mul(xval, yBoxedVal))
|
|
1415
|
+
}
|
|
1416
|
+
},
|
|
1417
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1418
|
+
let xval = BI.toFloat64(x)
|
|
1419
|
+
let yBoxedVal = boxedFloat64Number(y)
|
|
1420
|
+
if (isDivide) {
|
|
1421
|
+
newFloat64(WasmF64.div(xval, yBoxedVal))
|
|
1422
|
+
} else {
|
|
1423
|
+
newFloat64(WasmF64.mul(xval, yBoxedVal))
|
|
1424
|
+
}
|
|
1425
|
+
},
|
|
1426
|
+
_ => {
|
|
1427
|
+
throw UnknownNumberTag
|
|
1428
|
+
},
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
@unsafe
|
|
955
1434
|
let numberTimesDivideSimpleHelp = (x, y, isDivide) => {
|
|
956
1435
|
// PRECONDITION: x is a "simple" number (value tag is 0) and isNumber(y)
|
|
957
1436
|
let xval = untagSimple(x) // <- actual int value of x
|
|
958
1437
|
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
959
1438
|
}
|
|
960
1439
|
|
|
1440
|
+
@unsafe
|
|
961
1441
|
let numberTimesDivideInt32Help = (xval, y, isDivide) => {
|
|
962
1442
|
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
963
1443
|
}
|
|
964
1444
|
|
|
1445
|
+
@unsafe
|
|
965
1446
|
let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
966
1447
|
// Division isn't commutative, so we actually need to do the work
|
|
967
|
-
let xNumerator =
|
|
968
|
-
let xDenominator =
|
|
1448
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1449
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
969
1450
|
if (isSimpleNumber(y)) {
|
|
970
|
-
|
|
1451
|
+
let yBig = BI.makeWrappedInt32(untagSimple(y))
|
|
1452
|
+
let ret = if (isDivide) {
|
|
971
1453
|
// (a / b) / y == a / (b * y)
|
|
972
|
-
let denominator =
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
reducedFraction64(xNumerator, denominator)
|
|
1454
|
+
let denominator = BI.mul(xDenominator, yBig)
|
|
1455
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1456
|
+
Memory.decRef(denominator)
|
|
1457
|
+
ret
|
|
977
1458
|
} else {
|
|
978
1459
|
// (a / b) * y == (a * y) / b
|
|
979
|
-
let numerator =
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
reducedFraction64(numerator, xDenominator)
|
|
1460
|
+
let numerator = BI.mul(xNumerator, yBig)
|
|
1461
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1462
|
+
Memory.decRef(numerator)
|
|
1463
|
+
ret
|
|
984
1464
|
}
|
|
1465
|
+
if (WasmI32.ne(yBig, ret)) {
|
|
1466
|
+
Memory.decRef(yBig)
|
|
1467
|
+
void
|
|
1468
|
+
}
|
|
1469
|
+
ret
|
|
985
1470
|
} else {
|
|
986
1471
|
let ytag = boxedNumberTag(y)
|
|
987
1472
|
match (ytag) {
|
|
988
1473
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
989
1474
|
// Same idea as above
|
|
990
|
-
|
|
1475
|
+
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1476
|
+
let ret = if (isDivide) {
|
|
991
1477
|
// (a / b) / y == a / (b * y)
|
|
992
|
-
let denominator =
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
reducedFraction64(xNumerator, denominator)
|
|
1478
|
+
let denominator = BI.mul(xDenominator, yBig)
|
|
1479
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1480
|
+
Memory.decRef(denominator)
|
|
1481
|
+
ret
|
|
997
1482
|
} else {
|
|
998
1483
|
// (a / b) * y == (a * y) / b
|
|
999
|
-
let numerator =
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
reducedFraction64(numerator, xDenominator)
|
|
1484
|
+
let numerator = BI.mul(xNumerator, yBig)
|
|
1485
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1486
|
+
Memory.decRef(numerator)
|
|
1487
|
+
ret
|
|
1004
1488
|
}
|
|
1489
|
+
Memory.decRef(yBig)
|
|
1490
|
+
ret
|
|
1005
1491
|
},
|
|
1006
1492
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1007
1493
|
// Same idea as above
|
|
1494
|
+
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1495
|
+
let ret = if (isDivide) {
|
|
1496
|
+
// (a / b) / y == a / (b * y)
|
|
1497
|
+
let denominator = BI.mul(xDenominator, yBig)
|
|
1498
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1499
|
+
Memory.decRef(denominator)
|
|
1500
|
+
ret
|
|
1501
|
+
} else {
|
|
1502
|
+
// (a / b) * y == (a * y) / b
|
|
1503
|
+
let numerator = BI.mul(xNumerator, yBig)
|
|
1504
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1505
|
+
Memory.decRef(numerator)
|
|
1506
|
+
ret
|
|
1507
|
+
}
|
|
1508
|
+
Memory.decRef(yBig)
|
|
1509
|
+
ret
|
|
1510
|
+
},
|
|
1511
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1008
1512
|
if (isDivide) {
|
|
1009
1513
|
// (a / b) / y == a / (b * y)
|
|
1010
|
-
let denominator =
|
|
1011
|
-
|
|
1514
|
+
let denominator = BI.mul(xDenominator, y)
|
|
1515
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1516
|
+
Memory.decRef(denominator)
|
|
1517
|
+
ret
|
|
1012
1518
|
} else {
|
|
1013
1519
|
// (a / b) * y == (a * y) / b
|
|
1014
|
-
let numerator =
|
|
1015
|
-
|
|
1520
|
+
let numerator = BI.mul(xNumerator, y)
|
|
1521
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1522
|
+
Memory.decRef(numerator)
|
|
1523
|
+
ret
|
|
1016
1524
|
}
|
|
1017
1525
|
},
|
|
1018
1526
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1019
|
-
let xNumerator =
|
|
1020
|
-
let xDenominator =
|
|
1021
|
-
let yNumerator =
|
|
1022
|
-
let yDenominator =
|
|
1527
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1528
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1529
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1530
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1023
1531
|
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
1024
1532
|
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
1025
1533
|
// TODO: (#304) this could maybe be written in a more overflow-proof way
|
|
1026
|
-
let numerator = if (isDivide)
|
|
1027
|
-
else
|
|
1028
|
-
let denominator = if (isDivide)
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
reducedFraction64(numerator, denominator)
|
|
1534
|
+
let numerator = if (isDivide) BI.mul(xNumerator, yDenominator)
|
|
1535
|
+
else BI.mul(xNumerator, yNumerator)
|
|
1536
|
+
let denominator = if (isDivide) BI.mul(xDenominator, yNumerator)
|
|
1537
|
+
else BI.mul(xDenominator, yDenominator)
|
|
1538
|
+
reducedFractionBigInt(numerator, denominator)
|
|
1032
1539
|
},
|
|
1033
1540
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1541
|
+
// TODO(#1190): We should probably use something more accurate if possible here
|
|
1542
|
+
let asFloat = WasmF32.demoteF64(
|
|
1543
|
+
WasmF64.div(BI.toFloat64(xNumerator), BI.toFloat64(xDenominator))
|
|
1037
1544
|
)
|
|
1038
1545
|
if (isDivide) {
|
|
1039
1546
|
newFloat32(WasmF32.div(asFloat, boxedFloat32Number(y)))
|
|
@@ -1042,9 +1549,10 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1042
1549
|
}
|
|
1043
1550
|
},
|
|
1044
1551
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1552
|
+
// TODO(#1190): We should probably use something more accurate if possible here
|
|
1045
1553
|
let asFloat = WasmF64.div(
|
|
1046
|
-
|
|
1047
|
-
|
|
1554
|
+
BI.toFloat64(xNumerator),
|
|
1555
|
+
BI.toFloat64(xDenominator)
|
|
1048
1556
|
)
|
|
1049
1557
|
if (isDivide) {
|
|
1050
1558
|
newFloat64(WasmF64.div(asFloat, boxedFloat64Number(y)))
|
|
@@ -1059,7 +1567,10 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1059
1567
|
}
|
|
1060
1568
|
}
|
|
1061
1569
|
|
|
1570
|
+
@unsafe
|
|
1062
1571
|
let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
1572
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1573
|
+
Memory.incRef(y)
|
|
1063
1574
|
let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
1064
1575
|
if (isDivide) {
|
|
1065
1576
|
newFloat64(WasmF64.div(x, yAsFloat))
|
|
@@ -1068,6 +1579,7 @@ let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
|
1068
1579
|
}
|
|
1069
1580
|
}
|
|
1070
1581
|
|
|
1582
|
+
@unsafe
|
|
1071
1583
|
let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
1072
1584
|
if (
|
|
1073
1585
|
isBoxedNumber(y) &&
|
|
@@ -1080,6 +1592,8 @@ let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
|
1080
1592
|
newFloat64(WasmF64.mul(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
1081
1593
|
}
|
|
1082
1594
|
} else {
|
|
1595
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1596
|
+
Memory.incRef(y)
|
|
1083
1597
|
let yAsFloat = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
1084
1598
|
if (isDivide) {
|
|
1085
1599
|
newFloat32(WasmF32.div(x, yAsFloat))
|
|
@@ -1089,6 +1603,7 @@ let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
|
1089
1603
|
}
|
|
1090
1604
|
}
|
|
1091
1605
|
|
|
1606
|
+
@unsafe
|
|
1092
1607
|
let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
1093
1608
|
if (isSimpleNumber(x)) {
|
|
1094
1609
|
numberTimesDivideSimpleHelp(x, y, isDivide)
|
|
@@ -1101,6 +1616,9 @@ let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
|
1101
1616
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1102
1617
|
numberTimesDivideInt64Help(boxedInt64Number(x), y, isDivide)
|
|
1103
1618
|
},
|
|
1619
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1620
|
+
numberTimesDivideBigIntHelp(x, y, isDivide)
|
|
1621
|
+
},
|
|
1104
1622
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1105
1623
|
numberTimesDivideRationalHelp(x, y, isDivide)
|
|
1106
1624
|
},
|
|
@@ -1117,10 +1635,12 @@ let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
|
1117
1635
|
}
|
|
1118
1636
|
}
|
|
1119
1637
|
|
|
1638
|
+
@unsafe
|
|
1120
1639
|
let numberTimes = (x, y) => {
|
|
1121
1640
|
WasmI32.toGrain(numberTimesDivideHelp(x, y, false)): Number
|
|
1122
1641
|
}
|
|
1123
1642
|
|
|
1643
|
+
@unsafe
|
|
1124
1644
|
let numberDivide = (x, y) => {
|
|
1125
1645
|
WasmI32.toGrain(numberTimesDivideHelp(x, y, true)): Number
|
|
1126
1646
|
}
|
|
@@ -1130,9 +1650,14 @@ let numberDivide = (x, y) => {
|
|
|
1130
1650
|
* (same schema as equal())
|
|
1131
1651
|
*/
|
|
1132
1652
|
|
|
1653
|
+
@unsafe
|
|
1133
1654
|
let i64abs = x => if (WasmI64.geS(x, 0N)) x else WasmI64.sub(0N, x)
|
|
1134
1655
|
|
|
1656
|
+
@unsafe
|
|
1135
1657
|
let numberMod = (x, y) => {
|
|
1658
|
+
// incRef x and y to reuse them via WasmI32.toGrain
|
|
1659
|
+
Memory.incRef(x)
|
|
1660
|
+
Memory.incRef(y)
|
|
1136
1661
|
let xval = coerceNumberToWasmI64(WasmI32.toGrain(x): Number)
|
|
1137
1662
|
let yval = coerceNumberToWasmI64(WasmI32.toGrain(y): Number)
|
|
1138
1663
|
if (WasmI64.eqz(yval)) {
|
|
@@ -1160,147 +1685,264 @@ let numberMod = (x, y) => {
|
|
|
1160
1685
|
* Coerce to float64 and then do comparisons
|
|
1161
1686
|
* TODO: (#305) Could probably be made more efficient
|
|
1162
1687
|
*/
|
|
1688
|
+
|
|
1689
|
+
@unsafe
|
|
1690
|
+
let cmpBigInt = (x: WasmI32, y: WasmI32) => {
|
|
1691
|
+
if (isSimpleNumber(y)) {
|
|
1692
|
+
BI.cmpI64(x, WasmI64.extendI32S(untagSimple(y)))
|
|
1693
|
+
} else {
|
|
1694
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1695
|
+
match (yBoxedNumberTag) {
|
|
1696
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1697
|
+
BI.cmpI64(x, WasmI64.extendI32S(boxedInt32Number(y)))
|
|
1698
|
+
},
|
|
1699
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1700
|
+
BI.cmpI64(x, boxedInt64Number(y))
|
|
1701
|
+
},
|
|
1702
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1703
|
+
BI.cmp(x, y)
|
|
1704
|
+
},
|
|
1705
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1706
|
+
let tmp = BI.mul(x, boxedRationalDenominator(y))
|
|
1707
|
+
let ret = BI.cmp(tmp, boxedRationalNumerator(y))
|
|
1708
|
+
Memory.decRef(tmp)
|
|
1709
|
+
ret
|
|
1710
|
+
},
|
|
1711
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1712
|
+
BI.cmpF32(x, boxedFloat32Number(y))
|
|
1713
|
+
},
|
|
1714
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1715
|
+
BI.cmpF64(x, boxedFloat64Number(y))
|
|
1716
|
+
},
|
|
1717
|
+
_ => {
|
|
1718
|
+
throw UnknownNumberTag
|
|
1719
|
+
},
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1163
1724
|
// TODO: (#305) is this safe? I think it's safe?
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
let
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1725
|
+
@unsafe
|
|
1726
|
+
export let (<) = (x: Number, y: Number) => {
|
|
1727
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1728
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1729
|
+
if (isBigInt(xw32)) {
|
|
1730
|
+
WasmI32.ltS(cmpBigInt(xw32, yw32), 0n)
|
|
1731
|
+
} else if (isBigInt(yw32)) {
|
|
1732
|
+
WasmI32.geS(cmpBigInt(yw32, xw32), 0n)
|
|
1733
|
+
} else {
|
|
1734
|
+
let xval = coerceNumberToWasmF64(x)
|
|
1735
|
+
let yval = coerceNumberToWasmF64(y)
|
|
1736
|
+
WasmF64.lt(xval, yval)
|
|
1737
|
+
}
|
|
1172
1738
|
}
|
|
1173
1739
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
let
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1740
|
+
@unsafe
|
|
1741
|
+
export let (>) = (x: Number, y: Number) => {
|
|
1742
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1743
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1744
|
+
if (isBigInt(xw32)) {
|
|
1745
|
+
WasmI32.gtS(cmpBigInt(xw32, yw32), 0n)
|
|
1746
|
+
} else if (isBigInt(yw32)) {
|
|
1747
|
+
WasmI32.leS(cmpBigInt(yw32, xw32), 0n)
|
|
1748
|
+
} else {
|
|
1749
|
+
let xval = coerceNumberToWasmF64(x)
|
|
1750
|
+
let yval = coerceNumberToWasmF64(y)
|
|
1751
|
+
WasmF64.gt(xval, yval)
|
|
1752
|
+
}
|
|
1182
1753
|
}
|
|
1183
1754
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
let
|
|
1187
|
-
let
|
|
1188
|
-
|
|
1189
|
-
|
|
1755
|
+
@unsafe
|
|
1756
|
+
export let (<=) = (x: Number, y: Number) => {
|
|
1757
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1758
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1759
|
+
if (isBigInt(xw32)) {
|
|
1760
|
+
WasmI32.leS(cmpBigInt(xw32, yw32), 0n)
|
|
1761
|
+
} else if (isBigInt(yw32)) {
|
|
1762
|
+
WasmI32.geS(cmpBigInt(yw32, xw32), 0n)
|
|
1190
1763
|
} else {
|
|
1191
|
-
|
|
1192
|
-
let
|
|
1193
|
-
|
|
1764
|
+
// Equality is finicky, so delegate
|
|
1765
|
+
let xval = coerceNumberToWasmF64(x)
|
|
1766
|
+
let yval = coerceNumberToWasmF64(y)
|
|
1767
|
+
if (WasmF64.lt(xval, yval)) {
|
|
1768
|
+
true
|
|
1769
|
+
} else {
|
|
1770
|
+
let x = WasmI32.fromGrain(x)
|
|
1771
|
+
let y = WasmI32.fromGrain(y)
|
|
1772
|
+
numberEqual(x, y)
|
|
1773
|
+
}
|
|
1194
1774
|
}
|
|
1195
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1196
|
-
Memory.decRef(WasmI32.fromGrain(y))
|
|
1197
|
-
Memory.decRef(WasmI32.fromGrain((<=)))
|
|
1198
|
-
ret
|
|
1199
1775
|
}
|
|
1200
1776
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
let
|
|
1204
|
-
let
|
|
1205
|
-
|
|
1206
|
-
|
|
1777
|
+
@unsafe
|
|
1778
|
+
export let (>=) = (x: Number, y: Number) => {
|
|
1779
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1780
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1781
|
+
if (isBigInt(xw32)) {
|
|
1782
|
+
WasmI32.leS(cmpBigInt(xw32, yw32), 0n)
|
|
1783
|
+
} else if (isBigInt(yw32)) {
|
|
1784
|
+
WasmI32.geS(cmpBigInt(yw32, xw32), 0n)
|
|
1207
1785
|
} else {
|
|
1208
|
-
|
|
1209
|
-
let
|
|
1210
|
-
|
|
1786
|
+
// Equality is finicky, so delegate
|
|
1787
|
+
let xval = coerceNumberToWasmF64(x)
|
|
1788
|
+
let yval = coerceNumberToWasmF64(y)
|
|
1789
|
+
if (WasmF64.gt(xval, yval)) {
|
|
1790
|
+
true
|
|
1791
|
+
} else {
|
|
1792
|
+
let x = WasmI32.fromGrain(x)
|
|
1793
|
+
let y = WasmI32.fromGrain(y)
|
|
1794
|
+
numberEqual(x, y)
|
|
1795
|
+
}
|
|
1211
1796
|
}
|
|
1212
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1213
|
-
Memory.decRef(WasmI32.fromGrain(y))
|
|
1214
|
-
Memory.decRef(WasmI32.fromGrain((>=)))
|
|
1215
|
-
ret
|
|
1216
1797
|
}
|
|
1217
1798
|
|
|
1218
1799
|
/*
|
|
1219
1800
|
* ===== EQUAL =====
|
|
1220
1801
|
*/
|
|
1221
1802
|
|
|
1222
|
-
|
|
1803
|
+
@unsafe
|
|
1804
|
+
export let numberEq = (x: Number, y: Number) => {
|
|
1223
1805
|
let x = WasmI32.fromGrain(x)
|
|
1224
1806
|
let y = WasmI32.fromGrain(y)
|
|
1225
|
-
|
|
1226
|
-
Memory.decRef(x)
|
|
1227
|
-
Memory.decRef(y)
|
|
1228
|
-
Memory.decRef(WasmI32.fromGrain(numberEq))
|
|
1229
|
-
ret
|
|
1807
|
+
numberEqual(x, y)
|
|
1230
1808
|
}
|
|
1231
1809
|
|
|
1232
1810
|
/*
|
|
1233
1811
|
* ===== LOGICAL OPERATIONS =====
|
|
1234
|
-
* Only valid for int-like numbers. Coerce to i64 and do operations
|
|
1812
|
+
* Only valid for int-like numbers. Coerce to i64/bigInt and do operations
|
|
1235
1813
|
*/
|
|
1236
1814
|
// TODO: (#306) Semantics around when things should stay i32/i64
|
|
1237
1815
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
let
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1816
|
+
@unsafe
|
|
1817
|
+
export let lnot = (x: Number) => {
|
|
1818
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1819
|
+
if (isBigInt(xw32)) {
|
|
1820
|
+
WasmI32.toGrain(reducedBigInteger(BI.bitwiseNot(xw32))): Number
|
|
1821
|
+
} else {
|
|
1822
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1823
|
+
WasmI32.toGrain(reducedInteger(i64not(xval))): Number
|
|
1824
|
+
}
|
|
1244
1825
|
}
|
|
1245
1826
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
let
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1827
|
+
@unsafe
|
|
1828
|
+
export let (<<) = (x: Number, y: Number) => {
|
|
1829
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1830
|
+
if (isBigInt(xw32)) {
|
|
1831
|
+
let yval = coerceNumberToWasmI32(y)
|
|
1832
|
+
WasmI32.toGrain(reducedBigInteger(BI.shl(xw32, yval))): Number
|
|
1833
|
+
} else {
|
|
1834
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1835
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1836
|
+
WasmI32.toGrain(reducedInteger(WasmI64.shl(xval, yval))): Number
|
|
1837
|
+
}
|
|
1254
1838
|
}
|
|
1255
1839
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
let
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1840
|
+
@unsafe
|
|
1841
|
+
export let (>>>) = (x: Number, y: Number) => {
|
|
1842
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1843
|
+
if (isBigInt(xw32)) {
|
|
1844
|
+
let yval = coerceNumberToWasmI32(y)
|
|
1845
|
+
// [NOTE]: For BigInts, shrU is the same as shrS because there
|
|
1846
|
+
// are an *infinite* number of leading ones
|
|
1847
|
+
WasmI32.toGrain(reducedBigInteger(BI.shrS(xw32, yval))): Number
|
|
1848
|
+
} else {
|
|
1849
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1850
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1851
|
+
WasmI32.toGrain(reducedInteger(WasmI64.shrU(xval, yval))): Number
|
|
1852
|
+
}
|
|
1264
1853
|
}
|
|
1265
1854
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
let
|
|
1269
|
-
let
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1855
|
+
@unsafe
|
|
1856
|
+
export let (&) = (x: Number, y: Number) => {
|
|
1857
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1858
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1859
|
+
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
1860
|
+
let xval = coerceNumberToBigInt(x)
|
|
1861
|
+
let yval = coerceNumberToBigInt(y)
|
|
1862
|
+
let ret = WasmI32.toGrain(
|
|
1863
|
+
reducedBigInteger(BI.bitwiseAnd(xval, yval))
|
|
1864
|
+
): Number
|
|
1865
|
+
if (!WasmI32.eq(xw32, xval)) {
|
|
1866
|
+
Memory.decRef(xval)
|
|
1867
|
+
void
|
|
1868
|
+
}
|
|
1869
|
+
if (!WasmI32.eq(yw32, yval)) {
|
|
1870
|
+
Memory.decRef(yval)
|
|
1871
|
+
void
|
|
1872
|
+
}
|
|
1873
|
+
ret
|
|
1874
|
+
} else {
|
|
1875
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1876
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1877
|
+
WasmI32.toGrain(reducedInteger(WasmI64.and(xval, yval))): Number
|
|
1878
|
+
}
|
|
1274
1879
|
}
|
|
1275
1880
|
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
let
|
|
1279
|
-
let
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1881
|
+
@unsafe
|
|
1882
|
+
export let (|) = (x: Number, y: Number) => {
|
|
1883
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1884
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1885
|
+
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
1886
|
+
let xval = coerceNumberToBigInt(x)
|
|
1887
|
+
let yval = coerceNumberToBigInt(y)
|
|
1888
|
+
let ret = WasmI32.toGrain(
|
|
1889
|
+
reducedBigInteger(BI.bitwiseOr(xval, yval))
|
|
1890
|
+
): Number
|
|
1891
|
+
if (!WasmI32.eq(xw32, xval)) {
|
|
1892
|
+
Memory.decRef(xval)
|
|
1893
|
+
void
|
|
1894
|
+
}
|
|
1895
|
+
if (!WasmI32.eq(yw32, yval)) {
|
|
1896
|
+
Memory.decRef(yval)
|
|
1897
|
+
void
|
|
1898
|
+
}
|
|
1899
|
+
ret
|
|
1900
|
+
} else {
|
|
1901
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1902
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1903
|
+
WasmI32.toGrain(reducedInteger(WasmI64.or(xval, yval))): Number
|
|
1904
|
+
}
|
|
1284
1905
|
}
|
|
1285
1906
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
let
|
|
1289
|
-
let
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1907
|
+
@unsafe
|
|
1908
|
+
export let (^) = (x: Number, y: Number) => {
|
|
1909
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1910
|
+
let yw32 = WasmI32.fromGrain(y)
|
|
1911
|
+
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
1912
|
+
let xval = coerceNumberToBigInt(x)
|
|
1913
|
+
let yval = coerceNumberToBigInt(y)
|
|
1914
|
+
let ret = WasmI32.toGrain(
|
|
1915
|
+
reducedBigInteger(BI.bitwiseXor(xval, yval))
|
|
1916
|
+
): Number
|
|
1917
|
+
if (!WasmI32.eq(xw32, xval)) {
|
|
1918
|
+
Memory.decRef(xval)
|
|
1919
|
+
void
|
|
1920
|
+
}
|
|
1921
|
+
if (!WasmI32.eq(yw32, yval)) {
|
|
1922
|
+
Memory.decRef(yval)
|
|
1923
|
+
void
|
|
1924
|
+
}
|
|
1925
|
+
ret
|
|
1926
|
+
} else {
|
|
1927
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1928
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1929
|
+
WasmI32.toGrain(reducedInteger(WasmI64.xor(xval, yval))): Number
|
|
1930
|
+
}
|
|
1294
1931
|
}
|
|
1295
1932
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
let
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1933
|
+
@unsafe
|
|
1934
|
+
export let (>>) = (x: Number, y: Number) => {
|
|
1935
|
+
let xw32 = WasmI32.fromGrain(x)
|
|
1936
|
+
if (isBigInt(xw32)) {
|
|
1937
|
+
let yval = coerceNumberToWasmI32(y)
|
|
1938
|
+
// [NOTE]: For BigInts, shrU is the same as shrS because there
|
|
1939
|
+
// are an *infinite* number of leading ones
|
|
1940
|
+
WasmI32.toGrain(reducedBigInteger(BI.shrS(xw32, yval))): Number
|
|
1941
|
+
} else {
|
|
1942
|
+
let xval = coerceNumberToWasmI64(x)
|
|
1943
|
+
let yval = coerceNumberToWasmI64(y)
|
|
1944
|
+
WasmI32.toGrain(reducedInteger(WasmI64.shrS(xval, yval))): Number
|
|
1945
|
+
}
|
|
1304
1946
|
}
|
|
1305
1947
|
|
|
1306
1948
|
/// USER-EXPOSED COERCION FUNCTIONS
|
|
@@ -1308,151 +1950,186 @@ export let rec (>>) = (x: Number, y: Number) => {
|
|
|
1308
1950
|
// [NOTE]: Coercion is a *conservative* process! For example, even if a float is 1.0,
|
|
1309
1951
|
// we will fail if attempting to coerce to an int!
|
|
1310
1952
|
|
|
1953
|
+
@unsafe
|
|
1311
1954
|
export let rec coerceNumberToInt32 = (x: Number) => {
|
|
1312
1955
|
let x = WasmI32.fromGrain(x)
|
|
1313
1956
|
let result = if (
|
|
1314
1957
|
!isSimpleNumber(x) &&
|
|
1315
1958
|
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT32_BOXED_NUM_TAG)
|
|
1316
1959
|
) {
|
|
1317
|
-
// avoid extra malloc
|
|
1960
|
+
// avoid extra malloc and prevent x from being freed
|
|
1961
|
+
Memory.incRef(x)
|
|
1318
1962
|
x
|
|
1319
1963
|
} else {
|
|
1964
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
1965
|
+
Memory.incRef(x)
|
|
1320
1966
|
// can possibly fail
|
|
1321
1967
|
newInt32(coerceNumberToWasmI32(WasmI32.toGrain(x): Number))
|
|
1322
1968
|
}
|
|
1323
|
-
|
|
1324
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1325
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1326
|
-
void
|
|
1327
|
-
}
|
|
1328
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToInt32))
|
|
1329
|
-
ret
|
|
1969
|
+
WasmI32.toGrain(result): Int32
|
|
1330
1970
|
}
|
|
1331
1971
|
|
|
1972
|
+
@unsafe
|
|
1332
1973
|
export let rec coerceNumberToInt64 = (x: Number) => {
|
|
1333
1974
|
let x = WasmI32.fromGrain(x)
|
|
1334
1975
|
let result = if (
|
|
1335
1976
|
!isSimpleNumber(x) &&
|
|
1336
1977
|
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1337
1978
|
) {
|
|
1338
|
-
// avoid extra malloc
|
|
1979
|
+
// avoid extra malloc and prevent x from being freed
|
|
1980
|
+
Memory.incRef(x)
|
|
1339
1981
|
x
|
|
1340
1982
|
} else {
|
|
1983
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
1984
|
+
Memory.incRef(x)
|
|
1341
1985
|
newInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
|
|
1342
1986
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1987
|
+
WasmI32.toGrain(result): Int64
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
@unsafe
|
|
1991
|
+
export let rec coerceNumberToBigInt = (x: Number) => {
|
|
1992
|
+
let x = WasmI32.fromGrain(x)
|
|
1993
|
+
let result = if (isBigInt(x)) {
|
|
1994
|
+
// avoid extra malloc and prevent x from being freed
|
|
1995
|
+
Memory.incRef(x)
|
|
1996
|
+
x
|
|
1997
|
+
} else {
|
|
1998
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
1999
|
+
Memory.incRef(x)
|
|
2000
|
+
BI.makeWrappedInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
|
|
1347
2001
|
}
|
|
1348
|
-
|
|
1349
|
-
ret
|
|
2002
|
+
WasmI32.toGrain(result): BigInt
|
|
1350
2003
|
}
|
|
1351
2004
|
|
|
1352
|
-
|
|
2005
|
+
@unsafe
|
|
2006
|
+
export let coerceNumberToRational = (x: Number) => {
|
|
1353
2007
|
let x = WasmI32.fromGrain(x)
|
|
1354
2008
|
let result = if (isSimpleNumber(x)) {
|
|
1355
|
-
newRational(untagSimple(x), 1n)
|
|
2009
|
+
newRational(BI.makeWrappedInt32(untagSimple(x)), BI.makeWrappedInt32(1n))
|
|
1356
2010
|
} else {
|
|
1357
2011
|
let tag = boxedNumberTag(x)
|
|
1358
2012
|
if (WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)) {
|
|
2013
|
+
// avoid extra malloc and prevent x from being freed
|
|
2014
|
+
Memory.incRef(x)
|
|
1359
2015
|
x
|
|
1360
2016
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG)) {
|
|
1361
|
-
newRational(
|
|
2017
|
+
newRational(
|
|
2018
|
+
BI.makeWrappedInt32(boxedInt32Number(x)),
|
|
2019
|
+
BI.makeWrappedInt32(1n)
|
|
2020
|
+
)
|
|
1362
2021
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG)) {
|
|
1363
|
-
|
|
2022
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2023
|
+
Memory.incRef(x)
|
|
2024
|
+
newRational(
|
|
2025
|
+
BI.makeWrappedInt32(coerceNumberToWasmI32(WasmI32.toGrain(x): Number)),
|
|
2026
|
+
BI.makeWrappedInt32(1n)
|
|
2027
|
+
)
|
|
1364
2028
|
} else {
|
|
1365
2029
|
throw Exception.NumberNotRational
|
|
1366
2030
|
}
|
|
1367
2031
|
}
|
|
1368
|
-
|
|
1369
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1370
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1371
|
-
void
|
|
1372
|
-
}
|
|
1373
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToRational))
|
|
1374
|
-
ret
|
|
2032
|
+
WasmI32.toGrain(result): Rational
|
|
1375
2033
|
}
|
|
1376
2034
|
|
|
1377
|
-
|
|
2035
|
+
@unsafe
|
|
2036
|
+
export let coerceNumberToFloat32 = (x: Number) => {
|
|
1378
2037
|
let x = WasmI32.fromGrain(x)
|
|
1379
2038
|
let result = if (
|
|
1380
2039
|
!isSimpleNumber(x) &&
|
|
1381
2040
|
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)
|
|
1382
2041
|
) {
|
|
1383
|
-
// avoid extra malloc
|
|
2042
|
+
// avoid extra malloc and prevent x from being freed
|
|
2043
|
+
Memory.incRef(x)
|
|
1384
2044
|
x
|
|
1385
2045
|
} else {
|
|
2046
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2047
|
+
Memory.incRef(x)
|
|
1386
2048
|
newFloat32(coerceNumberToWasmF32(WasmI32.toGrain(x): Number))
|
|
1387
2049
|
}
|
|
1388
|
-
|
|
1389
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1390
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1391
|
-
void
|
|
1392
|
-
}
|
|
1393
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToFloat32))
|
|
1394
|
-
ret
|
|
2050
|
+
WasmI32.toGrain(result): Float32
|
|
1395
2051
|
}
|
|
1396
2052
|
|
|
1397
|
-
|
|
2053
|
+
@unsafe
|
|
2054
|
+
export let coerceNumberToFloat64 = (x: Number) => {
|
|
1398
2055
|
let x = WasmI32.fromGrain(x)
|
|
1399
2056
|
let result = if (
|
|
1400
2057
|
!isSimpleNumber(x) &&
|
|
1401
2058
|
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
1402
2059
|
) {
|
|
1403
|
-
// avoid extra malloc
|
|
2060
|
+
// avoid extra malloc and prevent x from being freed
|
|
2061
|
+
Memory.incRef(x)
|
|
1404
2062
|
x
|
|
1405
2063
|
} else {
|
|
2064
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2065
|
+
Memory.incRef(x)
|
|
1406
2066
|
newFloat64(coerceNumberToWasmF64(WasmI32.toGrain(x): Number))
|
|
1407
2067
|
}
|
|
1408
|
-
|
|
1409
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1410
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1411
|
-
void
|
|
1412
|
-
}
|
|
1413
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToFloat64))
|
|
1414
|
-
ret
|
|
2068
|
+
WasmI32.toGrain(result): Float64
|
|
1415
2069
|
}
|
|
1416
2070
|
|
|
1417
|
-
|
|
1418
|
-
export let
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
2071
|
+
@unsafe
|
|
2072
|
+
export let coerceInt32ToNumber = (x: Int32) => {
|
|
2073
|
+
WasmI32.toGrain(
|
|
2074
|
+
reducedInteger(WasmI64.extendI32S(boxedInt32Number(WasmI32.fromGrain(x))))
|
|
2075
|
+
): Number
|
|
1422
2076
|
}
|
|
1423
2077
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
2078
|
+
@unsafe
|
|
2079
|
+
export let coerceInt64ToNumber = (x: Int64) => {
|
|
2080
|
+
WasmI32.toGrain(
|
|
2081
|
+
reducedInteger(boxedInt64Number(WasmI32.fromGrain(x)))
|
|
2082
|
+
): Number
|
|
1428
2083
|
}
|
|
1429
2084
|
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
2085
|
+
@unsafe
|
|
2086
|
+
export let coerceBigIntToNumber = (x: BigInt) => {
|
|
2087
|
+
let x = WasmI32.fromGrain(x)
|
|
2088
|
+
// reducedBigInteger assumes that the bigint is dead,
|
|
2089
|
+
// but in our case, it is not
|
|
2090
|
+
Memory.incRef(x)
|
|
2091
|
+
WasmI32.toGrain(reducedBigInteger(x)): Number
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
@unsafe
|
|
2095
|
+
export let coerceRationalToNumber = (x: Rational) => {
|
|
2096
|
+
if (WasmI32.eq(boxedRationalDenominator(WasmI32.fromGrain(x)), 1n)) {
|
|
2097
|
+
WasmI32.toGrain(
|
|
2098
|
+
reducedInteger(
|
|
2099
|
+
WasmI64.extendI32S(boxedRationalNumerator(WasmI32.fromGrain(x)))
|
|
2100
|
+
)
|
|
2101
|
+
): Number
|
|
2102
|
+
} else {
|
|
2103
|
+
let x = WasmI32.fromGrain(x)
|
|
2104
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2105
|
+
Memory.incRef(x)
|
|
2106
|
+
WasmI32.toGrain(x): Number
|
|
2107
|
+
}
|
|
1434
2108
|
}
|
|
1435
2109
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
2110
|
+
@unsafe
|
|
2111
|
+
export let coerceFloat32ToNumber = (x: Float32) => {
|
|
2112
|
+
WasmI32.toGrain(
|
|
2113
|
+
newFloat64(WasmF64.promoteF32(boxedFloat32Number(WasmI32.fromGrain(x))))
|
|
2114
|
+
): Number
|
|
1440
2115
|
}
|
|
1441
2116
|
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
2117
|
+
@unsafe
|
|
2118
|
+
export let coerceFloat64ToNumber = (x: Float64) => {
|
|
2119
|
+
let x = WasmI32.fromGrain(x)
|
|
2120
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2121
|
+
Memory.incRef(x)
|
|
2122
|
+
WasmI32.toGrain(x): Number
|
|
1446
2123
|
}
|
|
1447
2124
|
|
|
1448
2125
|
/// USER-EXPOSED CONVERSION FUNCTIONS
|
|
1449
2126
|
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
ret
|
|
2127
|
+
@unsafe
|
|
2128
|
+
export let convertExactToInexact = (x: Number) => {
|
|
2129
|
+
x
|
|
1454
2130
|
}
|
|
1455
2131
|
|
|
2132
|
+
@unsafe
|
|
1456
2133
|
let convertInexactToExactHelp = x => {
|
|
1457
2134
|
if (isSimpleNumber(x)) {
|
|
1458
2135
|
x
|
|
@@ -1461,20 +2138,21 @@ let convertInexactToExactHelp = x => {
|
|
|
1461
2138
|
if (
|
|
1462
2139
|
WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG) ||
|
|
1463
2140
|
WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG) ||
|
|
2141
|
+
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) ||
|
|
1464
2142
|
WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)
|
|
1465
2143
|
) {
|
|
2144
|
+
Memory.incRef(x)
|
|
1466
2145
|
x
|
|
1467
2146
|
} else {
|
|
1468
2147
|
match (tag) {
|
|
1469
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => x,
|
|
1470
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => x,
|
|
1471
|
-
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => x,
|
|
1472
2148
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
2149
|
+
// TODO(#1191): Investigate if BigInt is more accurate
|
|
1473
2150
|
reducedInteger(
|
|
1474
2151
|
WasmI64.truncF32S(WasmF32.nearest(boxedFloat32Number(x)))
|
|
1475
2152
|
)
|
|
1476
2153
|
},
|
|
1477
2154
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
2155
|
+
// TODO(#1191): Investigate if BigInt is more accurate
|
|
1478
2156
|
reducedInteger(
|
|
1479
2157
|
WasmI64.truncF64S(WasmF64.nearest(boxedFloat64Number(x)))
|
|
1480
2158
|
)
|
|
@@ -1487,78 +2165,58 @@ let convertInexactToExactHelp = x => {
|
|
|
1487
2165
|
}
|
|
1488
2166
|
}
|
|
1489
2167
|
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
): Number
|
|
1494
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1495
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1496
|
-
void
|
|
1497
|
-
}
|
|
1498
|
-
Memory.decRef(WasmI32.fromGrain(convertInexactToExact))
|
|
1499
|
-
ret
|
|
2168
|
+
@unsafe
|
|
2169
|
+
export let convertInexactToExact = (x: Number) => {
|
|
2170
|
+
WasmI32.toGrain(convertInexactToExactHelp(WasmI32.fromGrain(x))): Number
|
|
1500
2171
|
}
|
|
1501
2172
|
|
|
1502
|
-
|
|
2173
|
+
@unsafe
|
|
2174
|
+
export let (+) = (x: Number, y: Number) => {
|
|
1503
2175
|
let x = WasmI32.fromGrain(x)
|
|
1504
2176
|
let y = WasmI32.fromGrain(y)
|
|
1505
|
-
|
|
1506
|
-
Memory.decRef(x)
|
|
1507
|
-
Memory.decRef(y)
|
|
1508
|
-
Memory.decRef(WasmI32.fromGrain((+)))
|
|
1509
|
-
ret
|
|
2177
|
+
numberAdd(x, y)
|
|
1510
2178
|
}
|
|
1511
2179
|
|
|
1512
|
-
|
|
2180
|
+
@unsafe
|
|
2181
|
+
export let (-) = (x: Number, y: Number) => {
|
|
1513
2182
|
let x = WasmI32.fromGrain(x)
|
|
1514
2183
|
let y = WasmI32.fromGrain(y)
|
|
1515
|
-
|
|
1516
|
-
Memory.decRef(x)
|
|
1517
|
-
Memory.decRef(y)
|
|
1518
|
-
Memory.decRef(WasmI32.fromGrain((-)))
|
|
1519
|
-
ret
|
|
2184
|
+
numberSub(x, y)
|
|
1520
2185
|
}
|
|
1521
2186
|
|
|
1522
|
-
|
|
2187
|
+
@unsafe
|
|
2188
|
+
export let (*) = (x: Number, y: Number) => {
|
|
1523
2189
|
let x = WasmI32.fromGrain(x)
|
|
1524
2190
|
let y = WasmI32.fromGrain(y)
|
|
1525
|
-
|
|
1526
|
-
Memory.decRef(x)
|
|
1527
|
-
Memory.decRef(y)
|
|
1528
|
-
Memory.decRef(WasmI32.fromGrain((*)))
|
|
1529
|
-
ret
|
|
2191
|
+
numberTimes(x, y)
|
|
1530
2192
|
}
|
|
1531
2193
|
|
|
1532
|
-
|
|
2194
|
+
@unsafe
|
|
2195
|
+
export let (/) = (x: Number, y: Number) => {
|
|
1533
2196
|
let x = WasmI32.fromGrain(x)
|
|
1534
2197
|
let y = WasmI32.fromGrain(y)
|
|
1535
|
-
|
|
1536
|
-
Memory.decRef(x)
|
|
1537
|
-
Memory.decRef(y)
|
|
1538
|
-
Memory.decRef(WasmI32.fromGrain((/)))
|
|
1539
|
-
ret
|
|
2198
|
+
numberDivide(x, y)
|
|
1540
2199
|
}
|
|
1541
2200
|
|
|
1542
|
-
|
|
2201
|
+
@unsafe
|
|
2202
|
+
export let (%) = (x: Number, y: Number) => {
|
|
1543
2203
|
let x = WasmI32.fromGrain(x)
|
|
1544
2204
|
let y = WasmI32.fromGrain(y)
|
|
1545
|
-
|
|
1546
|
-
Memory.decRef(x)
|
|
1547
|
-
Memory.decRef(y)
|
|
1548
|
-
Memory.decRef(WasmI32.fromGrain((%)))
|
|
1549
|
-
ret
|
|
2205
|
+
WasmI32.toGrain(numberMod(x, y)): Number
|
|
1550
2206
|
}
|
|
1551
2207
|
|
|
1552
2208
|
// inc/dec
|
|
1553
2209
|
|
|
1554
2210
|
export let incr = x => {
|
|
1555
|
-
Memory.incRef(WasmI32.fromGrain((+)))
|
|
1556
|
-
// skip incRef on x (to pass through)
|
|
1557
2211
|
x + 1
|
|
1558
2212
|
}
|
|
1559
2213
|
|
|
1560
2214
|
export let decr = x => {
|
|
1561
|
-
Memory.incRef(WasmI32.fromGrain((-)))
|
|
1562
|
-
// skip incRef on x (to pass through)
|
|
1563
2215
|
x - 1
|
|
1564
2216
|
}
|
|
2217
|
+
|
|
2218
|
+
@unsafe
|
|
2219
|
+
export let isBigInt = x => {
|
|
2220
|
+
let x = WasmI32.fromGrain(x)
|
|
2221
|
+
isBigInt(x)
|
|
2222
|
+
}
|