@grain/stdlib 0.4.4 → 0.5.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 +87 -0
- package/LICENSE +1 -1
- package/array.gr +92 -73
- package/array.md +18 -18
- package/bigint.gr +497 -0
- package/bigint.md +811 -0
- package/buffer.gr +56 -217
- package/buffer.md +24 -17
- package/bytes.gr +103 -205
- package/bytes.md +19 -0
- package/char.gr +152 -166
- package/char.md +200 -0
- package/exception.md +6 -0
- package/float32.gr +159 -82
- package/float32.md +315 -0
- package/float64.gr +163 -82
- package/float64.md +315 -0
- package/hash.gr +53 -49
- package/int32.gr +479 -230
- package/int32.md +937 -0
- package/int64.gr +479 -230
- package/int64.md +937 -0
- package/list.gr +530 -116
- package/list.md +1141 -0
- package/map.gr +302 -121
- package/map.md +525 -0
- package/number.gr +51 -57
- package/number.md +37 -3
- package/option.gr +25 -25
- package/option.md +1 -1
- package/package.json +3 -3
- package/pervasives.gr +504 -52
- package/pervasives.md +1116 -0
- package/queue.gr +8 -1
- package/queue.md +10 -0
- package/random.gr +196 -0
- package/random.md +179 -0
- package/range.gr +26 -26
- 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 -279
- package/runtime/dataStructures.md +391 -0
- package/runtime/debug.gr +0 -1
- package/runtime/debug.md +6 -0
- package/runtime/equal.gr +40 -37
- package/runtime/equal.md +6 -0
- package/runtime/exception.gr +28 -15
- package/runtime/exception.md +30 -0
- package/runtime/gc.gr +50 -20
- package/runtime/gc.md +36 -0
- package/runtime/malloc.gr +32 -22
- package/runtime/malloc.md +55 -0
- package/runtime/numberUtils.gr +297 -142
- package/runtime/numberUtils.md +54 -0
- package/runtime/numbers.gr +1204 -453
- package/runtime/numbers.md +300 -0
- package/runtime/string.gr +193 -228
- package/runtime/string.md +24 -0
- package/runtime/stringUtils.gr +62 -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.gr +10 -10
- package/runtime/unsafe/conv.md +71 -0
- package/runtime/unsafe/errors.md +204 -0
- package/runtime/unsafe/memory.gr +14 -3
- package/runtime/unsafe/memory.md +54 -0
- package/runtime/unsafe/printWasm.gr +4 -4
- package/runtime/unsafe/printWasm.md +24 -0
- package/runtime/unsafe/tags.gr +11 -10
- package/runtime/unsafe/tags.md +120 -0
- package/runtime/unsafe/wasmf32.gr +9 -2
- package/runtime/unsafe/wasmf32.md +168 -0
- package/runtime/unsafe/wasmf64.gr +9 -2
- package/runtime/unsafe/wasmf64.md +168 -0
- package/runtime/unsafe/wasmi32.gr +65 -47
- package/runtime/unsafe/wasmi32.md +282 -0
- package/runtime/unsafe/wasmi64.gr +78 -50
- 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 +200 -46
- package/runtime/wasi.md +839 -0
- package/set.gr +125 -121
- package/set.md +24 -21
- package/stack.gr +29 -29
- package/stack.md +4 -6
- package/string.gr +434 -415
- package/string.md +3 -3
- package/sys/file.gr +477 -482
- package/sys/process.gr +33 -47
- package/sys/random.gr +48 -20
- package/sys/random.md +38 -0
- package/sys/time.gr +12 -28
package/runtime/numbers.gr
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
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"
|
|
10
15
|
import WasmF64 from "runtime/unsafe/wasmf64"
|
|
11
16
|
|
|
12
|
-
primitive (!)
|
|
13
|
-
primitive (&&)
|
|
14
|
-
primitive (||)
|
|
15
|
-
primitive throw
|
|
17
|
+
primitive (!): Bool -> Bool = "@not"
|
|
18
|
+
primitive (&&): (Bool, Bool) -> Bool = "@and"
|
|
19
|
+
primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
20
|
+
primitive throw: Exception -> a = "@throw"
|
|
16
21
|
|
|
17
22
|
exception UnknownNumberTag
|
|
18
23
|
|
|
@@ -21,60 +26,82 @@ import {
|
|
|
21
26
|
newInt32,
|
|
22
27
|
newInt64,
|
|
23
28
|
newFloat32,
|
|
24
|
-
newFloat64
|
|
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
|
|
|
43
|
-
|
|
44
|
+
@unsafe
|
|
45
|
+
let tagSimple = x => {
|
|
44
46
|
WasmI32.xor(WasmI32.shl(x, 1n), 1n)
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
@unsafe
|
|
50
|
+
let untagSimple = x => {
|
|
48
51
|
WasmI32.shrS(x, 1n)
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
@unsafe
|
|
55
|
+
let isSimpleNumber = x => {
|
|
56
|
+
WasmI32.eq(
|
|
57
|
+
WasmI32.and(x, Tags._GRAIN_NUMBER_TAG_MASK),
|
|
58
|
+
Tags._GRAIN_NUMBER_TAG_TYPE
|
|
59
|
+
)
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
@unsafe
|
|
63
|
+
export let isBoxedNumber = x => {
|
|
64
|
+
if (
|
|
65
|
+
WasmI32.eq(
|
|
66
|
+
WasmI32.and(x, Tags._GRAIN_GENERIC_TAG_MASK),
|
|
67
|
+
Tags._GRAIN_GENERIC_HEAP_TAG_TYPE
|
|
68
|
+
)
|
|
69
|
+
) {
|
|
57
70
|
WasmI32.eq(WasmI32.load(x, 0n), Tags._GRAIN_BOXED_NUM_HEAP_TAG)
|
|
58
71
|
} else {
|
|
59
72
|
false
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
|
|
63
|
-
|
|
76
|
+
@unsafe
|
|
77
|
+
export let isFloat = x => {
|
|
64
78
|
if (isBoxedNumber(x)) {
|
|
65
79
|
let tag = WasmI32.load(x, 4n)
|
|
66
|
-
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
80
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
81
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
67
82
|
} else {
|
|
68
83
|
false
|
|
69
84
|
}
|
|
70
85
|
}
|
|
71
86
|
|
|
72
|
-
|
|
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
|
|
98
|
+
export let isNumber = x => {
|
|
73
99
|
// x is a number if it is a literal number or a boxed_num heap value
|
|
74
100
|
isSimpleNumber(x) || isBoxedNumber(x)
|
|
75
101
|
}
|
|
76
102
|
|
|
77
|
-
|
|
103
|
+
@unsafe
|
|
104
|
+
let safeI64toI32 = x => {
|
|
78
105
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
79
106
|
throw Exception.Overflow
|
|
80
107
|
} else {
|
|
@@ -82,12 +109,16 @@ let safeI64toI32 = (x) => {
|
|
|
82
109
|
}
|
|
83
110
|
}
|
|
84
111
|
|
|
85
|
-
|
|
112
|
+
@unsafe
|
|
113
|
+
let i32neg = x => WasmI32.sub(0n, x)
|
|
86
114
|
|
|
87
|
-
|
|
88
|
-
let
|
|
115
|
+
@unsafe
|
|
116
|
+
let i64not = x => WasmI64.xor(x, 0xffffffffffffffffN)
|
|
117
|
+
@unsafe
|
|
118
|
+
let i64neg = x => WasmI64.sub(0N, x)
|
|
89
119
|
|
|
90
120
|
// https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
|
121
|
+
@unsafe
|
|
91
122
|
let rec gcdHelp = (x, y) => {
|
|
92
123
|
if (WasmI64.eq(x, y) || WasmI64.eqz(x)) {
|
|
93
124
|
y
|
|
@@ -111,6 +142,7 @@ let rec gcdHelp = (x, y) => {
|
|
|
111
142
|
}
|
|
112
143
|
}
|
|
113
144
|
|
|
145
|
+
@unsafe
|
|
114
146
|
let gcd = (x, y) => {
|
|
115
147
|
// Algorithm above breaks on negatives, so
|
|
116
148
|
// we make sure that they are positive at the beginning
|
|
@@ -127,43 +159,90 @@ let gcd = (x, y) => {
|
|
|
127
159
|
gcdHelp(x, y)
|
|
128
160
|
}
|
|
129
161
|
|
|
162
|
+
@unsafe
|
|
130
163
|
let gcd32 = (x, y) => {
|
|
131
164
|
WasmI32.wrapI64(gcd(WasmI64.extendI32S(x), WasmI64.extendI32S(y)))
|
|
132
165
|
}
|
|
133
166
|
|
|
134
|
-
|
|
167
|
+
@unsafe
|
|
168
|
+
export let reducedInteger = x => {
|
|
135
169
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
136
170
|
newInt64(x)
|
|
137
|
-
} else if (
|
|
171
|
+
} else if (
|
|
172
|
+
WasmI64.gtS(x, WasmI64.shrS(_I32_MAX, 1N)) ||
|
|
173
|
+
WasmI64.ltS(x, WasmI64.shrS(_I32_MIN, 1N))
|
|
174
|
+
) {
|
|
138
175
|
newInt32(WasmI32.wrapI64(x))
|
|
139
176
|
} else {
|
|
140
177
|
tagSimple(WasmI32.wrapI64(x))
|
|
141
178
|
}
|
|
142
179
|
}
|
|
143
180
|
|
|
144
|
-
|
|
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) => {
|
|
145
198
|
let mut x = x
|
|
146
199
|
let mut y = y
|
|
200
|
+
let mut needsDecref = false
|
|
147
201
|
|
|
148
|
-
if (
|
|
202
|
+
if (BI.isNegative(y)) {
|
|
149
203
|
// Normalization 1: Never do negative/negative
|
|
150
204
|
// Normalization 2: Never allow a negative denominator
|
|
151
|
-
|
|
152
|
-
|
|
205
|
+
needsDecref = true
|
|
206
|
+
x = BI.negate(x)
|
|
207
|
+
y = BI.negate(y)
|
|
153
208
|
}
|
|
154
|
-
if (
|
|
209
|
+
if (BI.eqz(y)) {
|
|
155
210
|
throw Exception.DivisionByZero
|
|
156
211
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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)
|
|
160
225
|
} else {
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
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
|
|
164
241
|
}
|
|
242
|
+
ret
|
|
165
243
|
}
|
|
166
244
|
|
|
245
|
+
@unsafe
|
|
167
246
|
let reducedFraction64 = (x, y) => {
|
|
168
247
|
let mut x = x
|
|
169
248
|
let mut y = y
|
|
@@ -181,28 +260,10 @@ let reducedFraction64 = (x, y) => {
|
|
|
181
260
|
reducedInteger(WasmI64.divS(x, y))
|
|
182
261
|
} else {
|
|
183
262
|
let factor = gcd(x, y)
|
|
184
|
-
let xdiv =
|
|
185
|
-
let ydiv =
|
|
186
|
-
newRational(xdiv, ydiv)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
let safeI32Multiply = (x, y) => {
|
|
191
|
-
let prod = WasmI64.mul(WasmI64.extendI32S(x), WasmI64.extendI32S(y))
|
|
192
|
-
if (WasmI64.gtS(prod, _I32_MAX) || WasmI64.ltS(prod, _I32_MIN)) {
|
|
193
|
-
throw Exception.Overflow
|
|
263
|
+
let xdiv = WasmI64.divS(x, factor)
|
|
264
|
+
let ydiv = WasmI64.divS(y, factor)
|
|
265
|
+
newRational(BI.makeWrappedInt64(xdiv), BI.makeWrappedInt64(ydiv))
|
|
194
266
|
}
|
|
195
|
-
WasmI32.wrapI64(prod)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
let safeI64Multiply = (x, y) => {
|
|
199
|
-
let prod = WasmI64.mul(x, y)
|
|
200
|
-
if (WasmI64.ne(x, 0N)) {
|
|
201
|
-
if (WasmI64.ne(WasmI64.divS(prod, x), y)) {
|
|
202
|
-
throw Exception.Overflow
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
prod
|
|
206
267
|
}
|
|
207
268
|
|
|
208
269
|
// Accessor functions
|
|
@@ -228,36 +289,42 @@ let safeI64Multiply = (x, y) => {
|
|
|
228
289
|
* [numerator, denominator]
|
|
229
290
|
*/
|
|
230
291
|
|
|
231
|
-
|
|
292
|
+
@unsafe
|
|
293
|
+
export let boxedNumberTag = xptr => {
|
|
232
294
|
WasmI32.load(xptr, 4n)
|
|
233
295
|
}
|
|
234
296
|
|
|
235
|
-
|
|
297
|
+
@unsafe
|
|
298
|
+
export let boxedInt32Number = xptr => {
|
|
236
299
|
WasmI32.load(xptr, 8n)
|
|
237
300
|
}
|
|
238
301
|
|
|
239
|
-
|
|
302
|
+
@unsafe
|
|
303
|
+
export let boxedInt64Number = xptr => {
|
|
240
304
|
WasmI64.load(xptr, 8n)
|
|
241
305
|
}
|
|
242
306
|
|
|
243
|
-
|
|
307
|
+
@unsafe
|
|
308
|
+
export let boxedFloat32Number = xptr => {
|
|
244
309
|
WasmF32.load(xptr, 8n)
|
|
245
310
|
}
|
|
246
311
|
|
|
247
|
-
|
|
312
|
+
@unsafe
|
|
313
|
+
export let boxedFloat64Number = xptr => {
|
|
248
314
|
WasmF64.load(xptr, 8n)
|
|
249
315
|
}
|
|
250
316
|
|
|
251
|
-
|
|
317
|
+
@unsafe
|
|
318
|
+
export let boxedRationalNumerator = xptr => {
|
|
252
319
|
WasmI32.load(xptr, 8n)
|
|
253
320
|
}
|
|
254
321
|
|
|
255
|
-
|
|
322
|
+
@unsafe
|
|
323
|
+
export let boxedRationalDenominator = xptr => {
|
|
256
324
|
WasmI32.load(xptr, 12n)
|
|
257
325
|
}
|
|
258
326
|
|
|
259
|
-
|
|
260
|
-
|
|
327
|
+
@unsafe
|
|
261
328
|
export let coerceNumberToWasmF32 = (x: Number) => {
|
|
262
329
|
let x = WasmI32.fromGrain(x)
|
|
263
330
|
if (isSimpleNumber(x)) {
|
|
@@ -271,8 +338,14 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
271
338
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
272
339
|
WasmF32.convertI64S(boxedInt64Number(x))
|
|
273
340
|
},
|
|
341
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
342
|
+
BI.toFloat32(x)
|
|
343
|
+
},
|
|
274
344
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
275
|
-
WasmF32.div(
|
|
345
|
+
WasmF32.div(
|
|
346
|
+
BI.toFloat32(boxedRationalNumerator(x)),
|
|
347
|
+
BI.toFloat32(boxedRationalDenominator(x))
|
|
348
|
+
)
|
|
276
349
|
},
|
|
277
350
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
278
351
|
boxedFloat32Number(x)
|
|
@@ -288,11 +361,12 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
288
361
|
},
|
|
289
362
|
_ => {
|
|
290
363
|
throw UnknownNumberTag
|
|
291
|
-
}
|
|
364
|
+
},
|
|
292
365
|
}
|
|
293
366
|
}
|
|
294
367
|
}
|
|
295
368
|
|
|
369
|
+
@unsafe
|
|
296
370
|
export let coerceNumberToWasmF64 = (x: Number) => {
|
|
297
371
|
let x = WasmI32.fromGrain(x)
|
|
298
372
|
if (isSimpleNumber(x)) {
|
|
@@ -306,8 +380,14 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
306
380
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
307
381
|
WasmF64.convertI64S(boxedInt64Number(x))
|
|
308
382
|
},
|
|
383
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
384
|
+
BI.toFloat64(x)
|
|
385
|
+
},
|
|
309
386
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
310
|
-
WasmF64.div(
|
|
387
|
+
WasmF64.div(
|
|
388
|
+
BI.toFloat64(boxedRationalNumerator(x)),
|
|
389
|
+
BI.toFloat64(boxedRationalDenominator(x))
|
|
390
|
+
)
|
|
311
391
|
},
|
|
312
392
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
313
393
|
WasmF64.promoteF32(boxedFloat32Number(x))
|
|
@@ -317,11 +397,12 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
317
397
|
},
|
|
318
398
|
_ => {
|
|
319
399
|
throw UnknownNumberTag
|
|
320
|
-
}
|
|
400
|
+
},
|
|
321
401
|
}
|
|
322
402
|
}
|
|
323
403
|
}
|
|
324
404
|
|
|
405
|
+
@unsafe
|
|
325
406
|
export let coerceNumberToWasmI64 = (x: Number) => {
|
|
326
407
|
let x = WasmI32.fromGrain(x)
|
|
327
408
|
if (isSimpleNumber(x)) {
|
|
@@ -335,14 +416,18 @@ export let coerceNumberToWasmI64 = (x: Number) => {
|
|
|
335
416
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
336
417
|
boxedInt64Number(x)
|
|
337
418
|
},
|
|
419
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
420
|
+
BI.toInt64(x)
|
|
421
|
+
},
|
|
338
422
|
_ => {
|
|
339
423
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
340
424
|
throw Exception.NumberNotIntlike
|
|
341
|
-
}
|
|
425
|
+
},
|
|
342
426
|
}
|
|
343
427
|
}
|
|
344
428
|
}
|
|
345
429
|
|
|
430
|
+
@unsafe
|
|
346
431
|
export let coerceNumberToWasmI32 = (x: Number) => {
|
|
347
432
|
let x = WasmI32.fromGrain(x)
|
|
348
433
|
if (isSimpleNumber(x)) {
|
|
@@ -360,29 +445,63 @@ export let coerceNumberToWasmI32 = (x: Number) => {
|
|
|
360
445
|
}
|
|
361
446
|
WasmI32.wrapI64(int64)
|
|
362
447
|
},
|
|
448
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
449
|
+
BI.toInt32(x)
|
|
450
|
+
},
|
|
363
451
|
_ => {
|
|
364
452
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
365
453
|
throw Exception.NumberNotIntlike
|
|
366
|
-
}
|
|
454
|
+
},
|
|
367
455
|
}
|
|
368
456
|
}
|
|
369
457
|
}
|
|
370
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
|
+
},
|
|
477
|
+
_ => {
|
|
478
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
479
|
+
throw Exception.NumberNotIntlike
|
|
480
|
+
},
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
371
484
|
|
|
372
|
-
|
|
485
|
+
@unsafe
|
|
486
|
+
let isIntegerF32 = value => {
|
|
373
487
|
WasmF32.eq(value, WasmF32.trunc(value))
|
|
374
488
|
}
|
|
375
489
|
|
|
376
|
-
|
|
490
|
+
@unsafe
|
|
491
|
+
let isIntegerF64 = value => {
|
|
377
492
|
WasmF64.eq(value, WasmF64.trunc(value))
|
|
378
493
|
}
|
|
379
494
|
|
|
380
|
-
|
|
381
|
-
|
|
495
|
+
@unsafe
|
|
496
|
+
let isSafeIntegerF32 = value => {
|
|
497
|
+
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
498
|
+
WasmF32.eq(WasmF32.trunc(value), value)
|
|
382
499
|
}
|
|
383
500
|
|
|
384
|
-
|
|
385
|
-
|
|
501
|
+
@unsafe
|
|
502
|
+
let isSafeIntegerF64 = value => {
|
|
503
|
+
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
504
|
+
WasmF64.eq(WasmF64.trunc(value), value)
|
|
386
505
|
}
|
|
387
506
|
|
|
388
507
|
/** Number-aware equality checking
|
|
@@ -394,6 +513,7 @@ let isSafeIntegerF64 = (value) => {
|
|
|
394
513
|
* export them!
|
|
395
514
|
*/
|
|
396
515
|
|
|
516
|
+
@unsafe
|
|
397
517
|
let numberEqualSimpleHelp = (x, y) => {
|
|
398
518
|
// PRECONDITION: x is a "simple" number (value tag is 0) and x !== y and isNumber(y)
|
|
399
519
|
if (isSimpleNumber(y)) {
|
|
@@ -411,26 +531,31 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
411
531
|
let yBoxedVal = boxedInt64Number(y)
|
|
412
532
|
WasmI64.eq(WasmI64.extendI32S(xval), yBoxedVal)
|
|
413
533
|
},
|
|
534
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
535
|
+
WasmI32.eqz(BI.cmpI64(y, WasmI64.extendI32S(xval)))
|
|
536
|
+
},
|
|
414
537
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
415
538
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
416
539
|
false
|
|
417
540
|
},
|
|
418
541
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
419
542
|
let yBoxedVal = boxedFloat32Number(y)
|
|
420
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
543
|
+
isSafeIntegerF32(yBoxedVal) &&
|
|
544
|
+
WasmF32.eq(WasmF32.convertI32S(xval), yBoxedVal)
|
|
421
545
|
},
|
|
422
546
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
423
547
|
let yBoxedVal = boxedFloat64Number(y)
|
|
424
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
548
|
+
isSafeIntegerF64(yBoxedVal) &&
|
|
549
|
+
WasmF64.eq(WasmF64.convertI32S(xval), yBoxedVal)
|
|
425
550
|
},
|
|
426
551
|
_ => {
|
|
427
552
|
throw UnknownNumberTag
|
|
428
|
-
}
|
|
553
|
+
},
|
|
429
554
|
}
|
|
430
555
|
}
|
|
431
556
|
}
|
|
432
557
|
|
|
433
|
-
|
|
558
|
+
@unsafe
|
|
434
559
|
let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
435
560
|
// PRECONDITION: x !== y and isNumber(y)
|
|
436
561
|
// Basic number:
|
|
@@ -448,30 +573,37 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
448
573
|
let yBoxedVal = boxedInt64Number(y)
|
|
449
574
|
WasmI64.eq(xBoxedVal, yBoxedVal)
|
|
450
575
|
},
|
|
576
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
577
|
+
WasmI32.eqz(BI.cmpI64(y, xBoxedVal))
|
|
578
|
+
},
|
|
451
579
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
452
580
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
453
581
|
false
|
|
454
582
|
},
|
|
455
583
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
456
584
|
let yBoxedVal = boxedFloat32Number(y)
|
|
457
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
585
|
+
isSafeIntegerF32(yBoxedVal) &&
|
|
586
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF32S(yBoxedVal))
|
|
458
587
|
},
|
|
459
588
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
460
589
|
let yBoxedVal = boxedFloat64Number(y)
|
|
461
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
590
|
+
isSafeIntegerF64(yBoxedVal) &&
|
|
591
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF64S(yBoxedVal))
|
|
462
592
|
},
|
|
463
593
|
_ => {
|
|
464
594
|
throw UnknownNumberTag
|
|
465
|
-
}
|
|
595
|
+
},
|
|
466
596
|
}
|
|
467
597
|
}
|
|
468
598
|
}
|
|
469
599
|
|
|
600
|
+
@unsafe
|
|
470
601
|
let numberEqualInt32Help = (xBoxedVal, y) => {
|
|
471
602
|
// We can just pretend it's 64-bit for the equality check
|
|
472
603
|
numberEqualInt64Help(WasmI64.extendI32S(xBoxedVal), y)
|
|
473
604
|
}
|
|
474
605
|
|
|
606
|
+
@unsafe
|
|
475
607
|
let numberEqualRationalHelp = (xptr, y) => {
|
|
476
608
|
// PRECONDITION: x is rational and x !== y and isNumber(y)
|
|
477
609
|
// Basic number: (we know it's not equal, since we never store ints as rationals)
|
|
@@ -489,30 +621,40 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
489
621
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
490
622
|
false
|
|
491
623
|
},
|
|
624
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
625
|
+
false
|
|
626
|
+
},
|
|
492
627
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
493
628
|
let yNumerator = boxedRationalNumerator(y)
|
|
494
629
|
let yDenominator = boxedRationalDenominator(y)
|
|
495
|
-
|
|
630
|
+
BI.eq(xNumerator, yNumerator) && BI.eq(xDenominator, yDenominator)
|
|
496
631
|
},
|
|
497
632
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
498
633
|
let yBoxedVal = boxedFloat32Number(y)
|
|
499
|
-
let xAsFloat = WasmF32.div(
|
|
634
|
+
let xAsFloat = WasmF32.div(
|
|
635
|
+
BI.toFloat32(xNumerator),
|
|
636
|
+
BI.toFloat32(xDenominator)
|
|
637
|
+
)
|
|
500
638
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
501
639
|
WasmF32.eq(xAsFloat, yBoxedVal)
|
|
502
640
|
},
|
|
503
641
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
504
642
|
let yBoxedVal = boxedFloat64Number(y)
|
|
505
|
-
let xAsFloat = WasmF64.div(
|
|
643
|
+
let xAsFloat = WasmF64.div(
|
|
644
|
+
BI.toFloat64(xNumerator),
|
|
645
|
+
BI.toFloat64(xDenominator)
|
|
646
|
+
)
|
|
506
647
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
507
648
|
WasmF64.eq(xAsFloat, yBoxedVal)
|
|
508
649
|
},
|
|
509
650
|
_ => {
|
|
510
651
|
throw UnknownNumberTag
|
|
511
|
-
}
|
|
652
|
+
},
|
|
512
653
|
}
|
|
513
654
|
}
|
|
514
655
|
}
|
|
515
656
|
|
|
657
|
+
@unsafe
|
|
516
658
|
let numberEqualFloat64Help = (x, y) => {
|
|
517
659
|
let xIsInteger = isIntegerF64(x)
|
|
518
660
|
// Basic number:
|
|
@@ -530,10 +672,16 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
530
672
|
let yBoxedVal = boxedInt64Number(y)
|
|
531
673
|
isSafeIntegerF64(x) && WasmF64.eq(x, WasmF64.convertI64S(yBoxedVal))
|
|
532
674
|
},
|
|
675
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
676
|
+
WasmI32.eqz(BI.cmpF64(y, x))
|
|
677
|
+
},
|
|
533
678
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
534
679
|
let yNumerator = boxedRationalNumerator(y)
|
|
535
680
|
let yDenominator = boxedRationalDenominator(y)
|
|
536
|
-
let yAsFloat = WasmF64.div(
|
|
681
|
+
let yAsFloat = WasmF64.div(
|
|
682
|
+
BI.toFloat64(yNumerator),
|
|
683
|
+
BI.toFloat64(yDenominator)
|
|
684
|
+
)
|
|
537
685
|
WasmF64.eq(x, yAsFloat)
|
|
538
686
|
},
|
|
539
687
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
@@ -548,11 +696,12 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
548
696
|
},
|
|
549
697
|
_ => {
|
|
550
698
|
throw UnknownNumberTag
|
|
551
|
-
}
|
|
699
|
+
},
|
|
552
700
|
}
|
|
553
701
|
}
|
|
554
702
|
}
|
|
555
703
|
|
|
704
|
+
@unsafe
|
|
556
705
|
let numberEqualFloat32Help = (x, y) => {
|
|
557
706
|
let xIsInteger = isIntegerF32(x)
|
|
558
707
|
// Basic number:
|
|
@@ -568,11 +717,50 @@ let numberEqualFloat32Help = (x, y) => {
|
|
|
568
717
|
},
|
|
569
718
|
_ => {
|
|
570
719
|
numberEqualFloat64Help(WasmF64.promoteF32(x), y)
|
|
571
|
-
}
|
|
720
|
+
},
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
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
|
+
},
|
|
572
759
|
}
|
|
573
760
|
}
|
|
574
761
|
}
|
|
575
762
|
|
|
763
|
+
@unsafe
|
|
576
764
|
export let numberEqual = (x, y) => {
|
|
577
765
|
if (isSimpleNumber(x)) {
|
|
578
766
|
// Short circuit if non-pointer value is the same
|
|
@@ -598,9 +786,12 @@ export let numberEqual = (x, y) => {
|
|
|
598
786
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
599
787
|
numberEqualFloat64Help(boxedFloat64Number(x), y)
|
|
600
788
|
},
|
|
789
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
790
|
+
numberEqualBigIntHelp(x, y)
|
|
791
|
+
},
|
|
601
792
|
_ => {
|
|
602
793
|
throw UnknownNumberTag
|
|
603
|
-
}
|
|
794
|
+
},
|
|
604
795
|
}
|
|
605
796
|
}
|
|
606
797
|
}
|
|
@@ -610,6 +801,7 @@ export let numberEqual = (x, y) => {
|
|
|
610
801
|
* (same schema as equal())
|
|
611
802
|
*/
|
|
612
803
|
|
|
804
|
+
@unsafe
|
|
613
805
|
let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
614
806
|
// PRECONDITION: x is a "simple" number (value tag is 0) and isNumber(y)
|
|
615
807
|
if (isSimpleNumber(y)) {
|
|
@@ -628,209 +820,424 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
628
820
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
629
821
|
let xval = WasmI64.extendI32S(xval)
|
|
630
822
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
631
|
-
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
823
|
+
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
824
|
+
else WasmI64.add(xval, yBoxedVal)
|
|
632
825
|
reducedInteger(result)
|
|
633
826
|
},
|
|
634
827
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
635
828
|
let yBoxedVal = boxedInt64Number(y)
|
|
636
829
|
let xval64 = WasmI64.extendI32S(xval)
|
|
637
|
-
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
830
|
+
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
831
|
+
else WasmI64.add(xval64, yBoxedVal)
|
|
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)
|
|
642
847
|
} else {
|
|
643
848
|
reducedInteger(result)
|
|
644
849
|
}
|
|
645
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
|
+
},
|
|
646
858
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
647
|
-
let
|
|
648
|
-
let
|
|
649
|
-
let
|
|
650
|
-
let
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
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
|
|
655
870
|
},
|
|
656
871
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
657
872
|
let yBoxedVal = boxedFloat32Number(y)
|
|
658
873
|
let xval = WasmF32.convertI32S(xval)
|
|
659
|
-
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
874
|
+
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
875
|
+
else WasmF32.add(xval, yBoxedVal)
|
|
660
876
|
// TODO: (#304) is this safe?
|
|
661
877
|
newFloat32(result)
|
|
662
878
|
},
|
|
663
879
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
664
880
|
let yBoxedVal = boxedFloat64Number(y)
|
|
665
881
|
let xval = WasmF64.convertI32S(xval)
|
|
666
|
-
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
882
|
+
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
883
|
+
else WasmF64.add(xval, yBoxedVal)
|
|
667
884
|
newFloat64(result)
|
|
668
885
|
},
|
|
669
886
|
_ => {
|
|
670
887
|
throw UnknownNumberTag
|
|
671
|
-
}
|
|
888
|
+
},
|
|
672
889
|
}
|
|
673
890
|
}
|
|
674
891
|
}
|
|
675
892
|
|
|
893
|
+
@unsafe
|
|
676
894
|
let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
677
895
|
if (isSimpleNumber(y)) {
|
|
678
896
|
let yval = WasmI64.extendI32S(untagSimple(y))
|
|
679
897
|
let result = if (isSub) WasmI64.sub(xval, yval) else WasmI64.add(xval, yval)
|
|
680
|
-
if (
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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)
|
|
684
915
|
}
|
|
685
|
-
reducedInteger(result)
|
|
686
916
|
} else {
|
|
687
917
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
688
918
|
match (yBoxedNumberTag) {
|
|
689
919
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
690
920
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
691
|
-
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
921
|
+
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
922
|
+
else WasmI64.add(xval, yBoxedVal)
|
|
692
923
|
reducedInteger(result)
|
|
693
924
|
},
|
|
694
925
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
695
926
|
let yBoxedVal = boxedInt64Number(y)
|
|
696
927
|
let xval64 = xval
|
|
697
|
-
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
928
|
+
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
929
|
+
else WasmI64.add(xval64, yBoxedVal)
|
|
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)
|
|
702
945
|
} else {
|
|
703
946
|
reducedInteger(result)
|
|
704
947
|
}
|
|
705
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
|
+
},
|
|
706
956
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
707
|
-
let
|
|
708
|
-
let
|
|
709
|
-
let
|
|
710
|
-
let
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
|
715
968
|
},
|
|
716
969
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
717
970
|
let xval = WasmF32.convertI64S(xval)
|
|
718
971
|
let yBoxedVal = boxedFloat32Number(y)
|
|
719
|
-
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
720
|
-
|
|
972
|
+
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
973
|
+
else WasmF32.add(xval, yBoxedVal)
|
|
974
|
+
// TODO(#304): this isn't safe enough
|
|
721
975
|
newFloat32(result)
|
|
722
976
|
},
|
|
723
977
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
724
978
|
let xval = WasmF64.convertI64S(xval)
|
|
725
979
|
let yBoxedVal = boxedFloat64Number(y)
|
|
726
|
-
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
980
|
+
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
981
|
+
else WasmF64.add(xval, yBoxedVal)
|
|
727
982
|
newFloat64(result)
|
|
728
983
|
},
|
|
729
984
|
_ => {
|
|
730
985
|
throw UnknownNumberTag
|
|
731
|
-
}
|
|
986
|
+
},
|
|
732
987
|
}
|
|
733
988
|
}
|
|
734
989
|
}
|
|
735
990
|
|
|
991
|
+
@unsafe
|
|
736
992
|
let numberAddSubFloat32Help = (xval, y, isSub) => {
|
|
737
|
-
if (
|
|
993
|
+
if (
|
|
994
|
+
!isSimpleNumber(y) &&
|
|
995
|
+
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
996
|
+
) {
|
|
738
997
|
// Special case: promote to f64 if RHS is f64
|
|
739
998
|
let xval = WasmF64.promoteF32(xval)
|
|
740
999
|
let yval = boxedFloat64Number(y)
|
|
741
1000
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
742
1001
|
newFloat64(result)
|
|
743
1002
|
} else {
|
|
744
|
-
|
|
1003
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1004
|
+
Memory.incRef(y)
|
|
1005
|
+
let yval = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
745
1006
|
let result = if (isSub) WasmF32.sub(xval, yval) else WasmF32.add(xval, yval)
|
|
746
1007
|
newFloat32(result)
|
|
747
1008
|
}
|
|
748
1009
|
}
|
|
749
1010
|
|
|
1011
|
+
@unsafe
|
|
750
1012
|
let numberAddSubFloat64Help = (xval, y, isSub) => {
|
|
751
|
-
|
|
1013
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1014
|
+
Memory.incRef(y)
|
|
1015
|
+
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
752
1016
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
753
1017
|
newFloat64(result)
|
|
754
1018
|
}
|
|
755
1019
|
|
|
756
|
-
|
|
1020
|
+
@unsafe
|
|
757
1021
|
let numberAddSubInt32Help = (xval, y, isSub) => {
|
|
758
1022
|
numberAddSubInt64Help(WasmI64.extendI32S(xval), y, isSub)
|
|
759
1023
|
}
|
|
760
1024
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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)
|
|
764
1037
|
} else {
|
|
765
|
-
let
|
|
766
|
-
match (
|
|
1038
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1039
|
+
match (yBoxedNumberTag) {
|
|
767
1040
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
768
|
-
|
|
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)
|
|
769
1050
|
},
|
|
770
1051
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
771
|
-
|
|
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)
|
|
772
1069
|
},
|
|
773
1070
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
774
|
-
|
|
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
|
|
775
1080
|
},
|
|
776
1081
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
777
|
-
|
|
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)
|
|
778
1088
|
},
|
|
779
1089
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
780
|
-
|
|
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)
|
|
781
1095
|
},
|
|
782
1096
|
_ => {
|
|
783
1097
|
throw UnknownNumberTag
|
|
784
|
-
}
|
|
1098
|
+
},
|
|
785
1099
|
}
|
|
786
1100
|
}
|
|
787
|
-
}
|
|
788
|
-
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
@unsafe
|
|
1104
|
+
let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
1105
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1106
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
789
1107
|
if (isSimpleNumber(y)) {
|
|
790
|
-
|
|
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
|
|
791
1118
|
} else {
|
|
792
1119
|
let ytag = boxedNumberTag(y)
|
|
793
1120
|
match (ytag) {
|
|
794
1121
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
795
1122
|
// The one case we don't delegate is rational +/- rational
|
|
796
|
-
let xNumerator =
|
|
797
|
-
let xDenominator =
|
|
798
|
-
let yNumerator =
|
|
799
|
-
let yDenominator =
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
|
804
1133
|
} else {
|
|
805
|
-
let numerator1 =
|
|
806
|
-
let numerator2 =
|
|
807
|
-
let numerator = if (isSub)
|
|
808
|
-
|
|
809
|
-
|
|
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
|
|
810
1144
|
}
|
|
811
|
-
},
|
|
812
|
-
|
|
1145
|
+
},
|
|
1146
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
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
|
|
813
1156
|
},
|
|
814
1157
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
815
|
-
|
|
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
|
|
816
1176
|
},
|
|
817
1177
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
818
|
-
|
|
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)
|
|
819
1185
|
},
|
|
820
1186
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
821
|
-
|
|
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
|
|
822
1195
|
},
|
|
823
1196
|
_ => {
|
|
824
1197
|
throw UnknownNumberTag
|
|
825
|
-
}
|
|
1198
|
+
},
|
|
826
1199
|
}
|
|
827
1200
|
}
|
|
828
1201
|
}
|
|
829
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)
|
|
1212
|
+
},
|
|
1213
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
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)
|
|
1221
|
+
},
|
|
1222
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1223
|
+
numberAddSubFloat32Help(boxedFloat32Number(x), y, isSub)
|
|
1224
|
+
},
|
|
1225
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1226
|
+
numberAddSubFloat64Help(boxedFloat64Number(x), y, isSub)
|
|
1227
|
+
},
|
|
1228
|
+
_ => {
|
|
1229
|
+
throw UnknownNumberTag
|
|
1230
|
+
},
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
@unsafe
|
|
830
1236
|
let numberAdd = (x, y) => {
|
|
831
1237
|
WasmI32.toGrain(numberAddSubHelp(x, y, false)): Number
|
|
832
1238
|
}
|
|
833
1239
|
|
|
1240
|
+
@unsafe
|
|
834
1241
|
let numberSub = (x, y) => {
|
|
835
1242
|
WasmI32.toGrain(numberAddSubHelp(x, y, true)): Number
|
|
836
1243
|
}
|
|
@@ -840,12 +1247,32 @@ let numberSub = (x, y) => {
|
|
|
840
1247
|
* (same schema as equal())
|
|
841
1248
|
*/
|
|
842
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
|
|
843
1270
|
let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
844
1271
|
if (isSimpleNumber(y)) {
|
|
845
1272
|
if (isDivide) {
|
|
846
1273
|
reducedFraction64(xval, WasmI64.extendI32S(untagSimple(y)))
|
|
847
1274
|
} else {
|
|
848
|
-
|
|
1275
|
+
safeI64Multiply(xval, WasmI64.extendI32S(untagSimple(y)))
|
|
849
1276
|
}
|
|
850
1277
|
} else {
|
|
851
1278
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
@@ -855,7 +1282,7 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
855
1282
|
if (isDivide) {
|
|
856
1283
|
reducedFraction64(xval, yBoxedVal)
|
|
857
1284
|
} else {
|
|
858
|
-
|
|
1285
|
+
safeI64Multiply(xval, yBoxedVal)
|
|
859
1286
|
}
|
|
860
1287
|
},
|
|
861
1288
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
@@ -863,21 +1290,38 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
863
1290
|
if (isDivide) {
|
|
864
1291
|
reducedFraction64(xval, yBoxedVal)
|
|
865
1292
|
} else {
|
|
866
|
-
|
|
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))
|
|
867
1302
|
}
|
|
1303
|
+
Memory.decRef(xBig)
|
|
1304
|
+
ret
|
|
868
1305
|
},
|
|
869
1306
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
870
|
-
let yNumerator =
|
|
871
|
-
let yDenominator =
|
|
872
|
-
|
|
1307
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1308
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1309
|
+
let xBig = BI.makeWrappedInt64(xval)
|
|
1310
|
+
let ret = if (isDivide) {
|
|
873
1311
|
// x / (a / b) == (x * b) / a
|
|
874
|
-
let numerator =
|
|
875
|
-
|
|
1312
|
+
let numerator = BI.mul(xBig, yDenominator)
|
|
1313
|
+
let ret = reducedFractionBigInt(numerator, yNumerator)
|
|
1314
|
+
Memory.decRef(numerator)
|
|
1315
|
+
ret
|
|
876
1316
|
} else {
|
|
877
1317
|
// x * (a / b) == (x * a) / b
|
|
878
|
-
let numerator =
|
|
879
|
-
|
|
1318
|
+
let numerator = BI.mul(xBig, yNumerator)
|
|
1319
|
+
let ret = reducedFractionBigInt(numerator, yDenominator)
|
|
1320
|
+
Memory.decRef(numerator)
|
|
1321
|
+
ret
|
|
880
1322
|
}
|
|
1323
|
+
Memory.decRef(xBig)
|
|
1324
|
+
ret
|
|
881
1325
|
},
|
|
882
1326
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
883
1327
|
let xval = WasmF32.convertI64S(xval)
|
|
@@ -900,76 +1344,204 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
900
1344
|
},
|
|
901
1345
|
_ => {
|
|
902
1346
|
throw UnknownNumberTag
|
|
903
|
-
}
|
|
1347
|
+
},
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
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
|
+
},
|
|
904
1429
|
}
|
|
905
1430
|
}
|
|
906
1431
|
}
|
|
907
1432
|
|
|
1433
|
+
@unsafe
|
|
908
1434
|
let numberTimesDivideSimpleHelp = (x, y, isDivide) => {
|
|
909
1435
|
// PRECONDITION: x is a "simple" number (value tag is 0) and isNumber(y)
|
|
910
1436
|
let xval = untagSimple(x) // <- actual int value of x
|
|
911
1437
|
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
912
1438
|
}
|
|
913
1439
|
|
|
1440
|
+
@unsafe
|
|
914
1441
|
let numberTimesDivideInt32Help = (xval, y, isDivide) => {
|
|
915
1442
|
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
916
1443
|
}
|
|
917
1444
|
|
|
1445
|
+
@unsafe
|
|
918
1446
|
let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
919
1447
|
// Division isn't commutative, so we actually need to do the work
|
|
920
|
-
let xNumerator =
|
|
921
|
-
let xDenominator =
|
|
1448
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1449
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
922
1450
|
if (isSimpleNumber(y)) {
|
|
923
|
-
|
|
1451
|
+
let yBig = BI.makeWrappedInt32(untagSimple(y))
|
|
1452
|
+
let ret = if (isDivide) {
|
|
924
1453
|
// (a / b) / y == a / (b * y)
|
|
925
|
-
let denominator =
|
|
926
|
-
|
|
1454
|
+
let denominator = BI.mul(xDenominator, yBig)
|
|
1455
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1456
|
+
Memory.decRef(denominator)
|
|
1457
|
+
ret
|
|
927
1458
|
} else {
|
|
928
1459
|
// (a / b) * y == (a * y) / b
|
|
929
|
-
let numerator =
|
|
930
|
-
|
|
1460
|
+
let numerator = BI.mul(xNumerator, yBig)
|
|
1461
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1462
|
+
Memory.decRef(numerator)
|
|
1463
|
+
ret
|
|
931
1464
|
}
|
|
1465
|
+
if (WasmI32.ne(yBig, ret)) {
|
|
1466
|
+
Memory.decRef(yBig)
|
|
1467
|
+
void
|
|
1468
|
+
}
|
|
1469
|
+
ret
|
|
932
1470
|
} else {
|
|
933
1471
|
let ytag = boxedNumberTag(y)
|
|
934
1472
|
match (ytag) {
|
|
935
1473
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
936
1474
|
// Same idea as above
|
|
937
|
-
|
|
1475
|
+
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1476
|
+
let ret = if (isDivide) {
|
|
938
1477
|
// (a / b) / y == a / (b * y)
|
|
939
|
-
let denominator =
|
|
940
|
-
|
|
1478
|
+
let denominator = BI.mul(xDenominator, yBig)
|
|
1479
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1480
|
+
Memory.decRef(denominator)
|
|
1481
|
+
ret
|
|
941
1482
|
} else {
|
|
942
1483
|
// (a / b) * y == (a * y) / b
|
|
943
|
-
let numerator =
|
|
944
|
-
|
|
1484
|
+
let numerator = BI.mul(xNumerator, yBig)
|
|
1485
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1486
|
+
Memory.decRef(numerator)
|
|
1487
|
+
ret
|
|
945
1488
|
}
|
|
1489
|
+
Memory.decRef(yBig)
|
|
1490
|
+
ret
|
|
946
1491
|
},
|
|
947
1492
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
948
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) => {
|
|
949
1512
|
if (isDivide) {
|
|
950
1513
|
// (a / b) / y == a / (b * y)
|
|
951
|
-
let denominator =
|
|
952
|
-
|
|
1514
|
+
let denominator = BI.mul(xDenominator, y)
|
|
1515
|
+
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1516
|
+
Memory.decRef(denominator)
|
|
1517
|
+
ret
|
|
953
1518
|
} else {
|
|
954
1519
|
// (a / b) * y == (a * y) / b
|
|
955
|
-
let numerator =
|
|
956
|
-
|
|
1520
|
+
let numerator = BI.mul(xNumerator, y)
|
|
1521
|
+
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1522
|
+
Memory.decRef(numerator)
|
|
1523
|
+
ret
|
|
957
1524
|
}
|
|
958
1525
|
},
|
|
959
1526
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
960
|
-
let xNumerator =
|
|
961
|
-
let xDenominator =
|
|
962
|
-
let yNumerator =
|
|
963
|
-
let yDenominator =
|
|
1527
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1528
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1529
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1530
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
964
1531
|
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
965
1532
|
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
966
1533
|
// TODO: (#304) this could maybe be written in a more overflow-proof way
|
|
967
|
-
let numerator = if (isDivide)
|
|
968
|
-
|
|
969
|
-
|
|
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)
|
|
970
1539
|
},
|
|
971
1540
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
972
|
-
|
|
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))
|
|
1544
|
+
)
|
|
973
1545
|
if (isDivide) {
|
|
974
1546
|
newFloat32(WasmF32.div(asFloat, boxedFloat32Number(y)))
|
|
975
1547
|
} else {
|
|
@@ -977,7 +1549,11 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
977
1549
|
}
|
|
978
1550
|
},
|
|
979
1551
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
980
|
-
|
|
1552
|
+
// TODO(#1190): We should probably use something more accurate if possible here
|
|
1553
|
+
let asFloat = WasmF64.div(
|
|
1554
|
+
BI.toFloat64(xNumerator),
|
|
1555
|
+
BI.toFloat64(xDenominator)
|
|
1556
|
+
)
|
|
981
1557
|
if (isDivide) {
|
|
982
1558
|
newFloat64(WasmF64.div(asFloat, boxedFloat64Number(y)))
|
|
983
1559
|
} else {
|
|
@@ -986,13 +1562,16 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
986
1562
|
},
|
|
987
1563
|
_ => {
|
|
988
1564
|
throw UnknownNumberTag
|
|
989
|
-
}
|
|
1565
|
+
},
|
|
990
1566
|
}
|
|
991
1567
|
}
|
|
992
1568
|
}
|
|
993
1569
|
|
|
1570
|
+
@unsafe
|
|
994
1571
|
let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
995
|
-
|
|
1572
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1573
|
+
Memory.incRef(y)
|
|
1574
|
+
let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
996
1575
|
if (isDivide) {
|
|
997
1576
|
newFloat64(WasmF64.div(x, yAsFloat))
|
|
998
1577
|
} else {
|
|
@@ -1000,8 +1579,12 @@ let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
|
1000
1579
|
}
|
|
1001
1580
|
}
|
|
1002
1581
|
|
|
1582
|
+
@unsafe
|
|
1003
1583
|
let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
1004
|
-
if (
|
|
1584
|
+
if (
|
|
1585
|
+
isBoxedNumber(y) &&
|
|
1586
|
+
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1587
|
+
) {
|
|
1005
1588
|
// Special case: f32->f64 promotion
|
|
1006
1589
|
if (isDivide) {
|
|
1007
1590
|
newFloat64(WasmF64.div(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
@@ -1009,7 +1592,9 @@ let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
|
1009
1592
|
newFloat64(WasmF64.mul(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
1010
1593
|
}
|
|
1011
1594
|
} else {
|
|
1012
|
-
|
|
1595
|
+
// incRef y to reuse it via WasmI32.toGrain
|
|
1596
|
+
Memory.incRef(y)
|
|
1597
|
+
let yAsFloat = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
1013
1598
|
if (isDivide) {
|
|
1014
1599
|
newFloat32(WasmF32.div(x, yAsFloat))
|
|
1015
1600
|
} else {
|
|
@@ -1018,6 +1603,7 @@ let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
|
1018
1603
|
}
|
|
1019
1604
|
}
|
|
1020
1605
|
|
|
1606
|
+
@unsafe
|
|
1021
1607
|
let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
1022
1608
|
if (isSimpleNumber(x)) {
|
|
1023
1609
|
numberTimesDivideSimpleHelp(x, y, isDivide)
|
|
@@ -1030,6 +1616,9 @@ let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
|
1030
1616
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1031
1617
|
numberTimesDivideInt64Help(boxedInt64Number(x), y, isDivide)
|
|
1032
1618
|
},
|
|
1619
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1620
|
+
numberTimesDivideBigIntHelp(x, y, isDivide)
|
|
1621
|
+
},
|
|
1033
1622
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1034
1623
|
numberTimesDivideRationalHelp(x, y, isDivide)
|
|
1035
1624
|
},
|
|
@@ -1041,15 +1630,17 @@ let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
|
1041
1630
|
},
|
|
1042
1631
|
_ => {
|
|
1043
1632
|
throw UnknownNumberTag
|
|
1044
|
-
}
|
|
1633
|
+
},
|
|
1045
1634
|
}
|
|
1046
1635
|
}
|
|
1047
1636
|
}
|
|
1048
1637
|
|
|
1638
|
+
@unsafe
|
|
1049
1639
|
let numberTimes = (x, y) => {
|
|
1050
1640
|
WasmI32.toGrain(numberTimesDivideHelp(x, y, false)): Number
|
|
1051
1641
|
}
|
|
1052
1642
|
|
|
1643
|
+
@unsafe
|
|
1053
1644
|
let numberDivide = (x, y) => {
|
|
1054
1645
|
WasmI32.toGrain(numberTimesDivideHelp(x, y, true)): Number
|
|
1055
1646
|
}
|
|
@@ -1059,18 +1650,30 @@ let numberDivide = (x, y) => {
|
|
|
1059
1650
|
* (same schema as equal())
|
|
1060
1651
|
*/
|
|
1061
1652
|
|
|
1062
|
-
|
|
1653
|
+
@unsafe
|
|
1654
|
+
let i64abs = x => if (WasmI64.geS(x, 0N)) x else WasmI64.sub(0N, x)
|
|
1063
1655
|
|
|
1656
|
+
@unsafe
|
|
1064
1657
|
let numberMod = (x, y) => {
|
|
1065
|
-
|
|
1066
|
-
|
|
1658
|
+
// incRef x and y to reuse them via WasmI32.toGrain
|
|
1659
|
+
Memory.incRef(x)
|
|
1660
|
+
Memory.incRef(y)
|
|
1661
|
+
let xval = coerceNumberToWasmI64(WasmI32.toGrain(x): Number)
|
|
1662
|
+
let yval = coerceNumberToWasmI64(WasmI32.toGrain(y): Number)
|
|
1067
1663
|
if (WasmI64.eqz(yval)) {
|
|
1068
1664
|
throw Exception.ModuloByZero
|
|
1069
1665
|
}
|
|
1070
1666
|
// We implement true modulo
|
|
1071
|
-
if (
|
|
1667
|
+
if (
|
|
1668
|
+
WasmI64.ltS(xval, 0N) && WasmI64.gtS(yval, 0N) ||
|
|
1669
|
+
WasmI64.gtS(xval, 0N) && WasmI64.ltS(yval, 0N)
|
|
1670
|
+
) {
|
|
1072
1671
|
let modval = WasmI64.remS(i64abs(xval), i64abs(yval))
|
|
1073
|
-
let result = if (WasmI64.ne(modval, 0N))
|
|
1672
|
+
let result = if (WasmI64.ne(modval, 0N))
|
|
1673
|
+
WasmI64.mul(
|
|
1674
|
+
WasmI64.sub(i64abs(yval), modval),
|
|
1675
|
+
if (WasmI64.ltS(yval, 0N)) -1N else 1N
|
|
1676
|
+
) else modval
|
|
1074
1677
|
reducedInteger(result)
|
|
1075
1678
|
} else {
|
|
1076
1679
|
reducedInteger(WasmI64.remS(xval, yval))
|
|
@@ -1082,384 +1685,532 @@ let numberMod = (x, y) => {
|
|
|
1082
1685
|
* Coerce to float64 and then do comparisons
|
|
1083
1686
|
* TODO: (#305) Could probably be made more efficient
|
|
1084
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
|
+
|
|
1085
1724
|
// TODO: (#305) is this safe? I think it's safe?
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
let
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
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
|
+
}
|
|
1094
1738
|
}
|
|
1095
1739
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
let
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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
|
+
}
|
|
1104
1753
|
}
|
|
1105
1754
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
let
|
|
1109
|
-
let
|
|
1110
|
-
|
|
1111
|
-
|
|
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)
|
|
1112
1763
|
} else {
|
|
1113
|
-
|
|
1114
|
-
let
|
|
1115
|
-
|
|
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
|
+
}
|
|
1116
1774
|
}
|
|
1117
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1118
|
-
Memory.decRef(WasmI32.fromGrain(y))
|
|
1119
|
-
Memory.decRef(WasmI32.fromGrain((<=)))
|
|
1120
|
-
ret
|
|
1121
1775
|
}
|
|
1122
1776
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
let
|
|
1126
|
-
let
|
|
1127
|
-
|
|
1128
|
-
|
|
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)
|
|
1129
1785
|
} else {
|
|
1130
|
-
|
|
1131
|
-
let
|
|
1132
|
-
|
|
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
|
+
}
|
|
1133
1796
|
}
|
|
1134
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1135
|
-
Memory.decRef(WasmI32.fromGrain(y))
|
|
1136
|
-
Memory.decRef(WasmI32.fromGrain((>=)))
|
|
1137
|
-
ret
|
|
1138
1797
|
}
|
|
1139
1798
|
|
|
1140
1799
|
/*
|
|
1141
1800
|
* ===== EQUAL =====
|
|
1142
1801
|
*/
|
|
1143
1802
|
|
|
1144
|
-
|
|
1803
|
+
@unsafe
|
|
1804
|
+
export let numberEq = (x: Number, y: Number) => {
|
|
1145
1805
|
let x = WasmI32.fromGrain(x)
|
|
1146
1806
|
let y = WasmI32.fromGrain(y)
|
|
1147
|
-
|
|
1148
|
-
Memory.decRef(x)
|
|
1149
|
-
Memory.decRef(y)
|
|
1150
|
-
Memory.decRef(WasmI32.fromGrain(numberEq))
|
|
1151
|
-
ret
|
|
1807
|
+
numberEqual(x, y)
|
|
1152
1808
|
}
|
|
1153
1809
|
|
|
1154
1810
|
/*
|
|
1155
1811
|
* ===== LOGICAL OPERATIONS =====
|
|
1156
|
-
* 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
|
|
1157
1813
|
*/
|
|
1158
1814
|
// TODO: (#306) Semantics around when things should stay i32/i64
|
|
1159
1815
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
let
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
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
|
+
}
|
|
1166
1825
|
}
|
|
1167
1826
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
let
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
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
|
+
}
|
|
1176
1838
|
}
|
|
1177
1839
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
let
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
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
|
+
}
|
|
1186
1853
|
}
|
|
1187
1854
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
let
|
|
1191
|
-
let
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
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
|
+
}
|
|
1196
1879
|
}
|
|
1197
1880
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
let
|
|
1201
|
-
let
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
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
|
+
}
|
|
1206
1905
|
}
|
|
1207
1906
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
let
|
|
1211
|
-
let
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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
|
+
}
|
|
1216
1931
|
}
|
|
1217
1932
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
let
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
+
}
|
|
1226
1946
|
}
|
|
1227
1947
|
|
|
1228
|
-
|
|
1229
1948
|
/// USER-EXPOSED COERCION FUNCTIONS
|
|
1230
1949
|
//
|
|
1231
1950
|
// [NOTE]: Coercion is a *conservative* process! For example, even if a float is 1.0,
|
|
1232
1951
|
// we will fail if attempting to coerce to an int!
|
|
1233
1952
|
|
|
1953
|
+
@unsafe
|
|
1234
1954
|
export let rec coerceNumberToInt32 = (x: Number) => {
|
|
1235
1955
|
let x = WasmI32.fromGrain(x)
|
|
1236
|
-
let result = if (
|
|
1237
|
-
|
|
1956
|
+
let result = if (
|
|
1957
|
+
!isSimpleNumber(x) &&
|
|
1958
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT32_BOXED_NUM_TAG)
|
|
1959
|
+
) {
|
|
1960
|
+
// avoid extra malloc and prevent x from being freed
|
|
1961
|
+
Memory.incRef(x)
|
|
1238
1962
|
x
|
|
1239
1963
|
} else {
|
|
1964
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
1965
|
+
Memory.incRef(x)
|
|
1240
1966
|
// can possibly fail
|
|
1241
|
-
newInt32(coerceNumberToWasmI32(WasmI32.toGrain(x)
|
|
1242
|
-
}
|
|
1243
|
-
let ret = WasmI32.toGrain(result): Int32
|
|
1244
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1245
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1246
|
-
void
|
|
1967
|
+
newInt32(coerceNumberToWasmI32(WasmI32.toGrain(x): Number))
|
|
1247
1968
|
}
|
|
1248
|
-
|
|
1249
|
-
ret
|
|
1969
|
+
WasmI32.toGrain(result): Int32
|
|
1250
1970
|
}
|
|
1251
1971
|
|
|
1972
|
+
@unsafe
|
|
1252
1973
|
export let rec coerceNumberToInt64 = (x: Number) => {
|
|
1253
1974
|
let x = WasmI32.fromGrain(x)
|
|
1254
|
-
let result = if (
|
|
1255
|
-
|
|
1975
|
+
let result = if (
|
|
1976
|
+
!isSimpleNumber(x) &&
|
|
1977
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1978
|
+
) {
|
|
1979
|
+
// avoid extra malloc and prevent x from being freed
|
|
1980
|
+
Memory.incRef(x)
|
|
1256
1981
|
x
|
|
1257
1982
|
} else {
|
|
1258
|
-
|
|
1983
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
1984
|
+
Memory.incRef(x)
|
|
1985
|
+
newInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
|
|
1259
1986
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
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))
|
|
1264
2001
|
}
|
|
1265
|
-
|
|
1266
|
-
ret
|
|
2002
|
+
WasmI32.toGrain(result): BigInt
|
|
1267
2003
|
}
|
|
1268
2004
|
|
|
1269
|
-
|
|
2005
|
+
@unsafe
|
|
2006
|
+
export let coerceNumberToRational = (x: Number) => {
|
|
1270
2007
|
let x = WasmI32.fromGrain(x)
|
|
1271
2008
|
let result = if (isSimpleNumber(x)) {
|
|
1272
|
-
newRational(untagSimple(x), 1n)
|
|
2009
|
+
newRational(BI.makeWrappedInt32(untagSimple(x)), BI.makeWrappedInt32(1n))
|
|
1273
2010
|
} else {
|
|
1274
2011
|
let tag = boxedNumberTag(x)
|
|
1275
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)
|
|
1276
2015
|
x
|
|
1277
2016
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG)) {
|
|
1278
|
-
newRational(
|
|
2017
|
+
newRational(
|
|
2018
|
+
BI.makeWrappedInt32(boxedInt32Number(x)),
|
|
2019
|
+
BI.makeWrappedInt32(1n)
|
|
2020
|
+
)
|
|
1279
2021
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG)) {
|
|
1280
|
-
|
|
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
|
+
)
|
|
1281
2028
|
} else {
|
|
1282
2029
|
throw Exception.NumberNotRational
|
|
1283
2030
|
}
|
|
1284
2031
|
}
|
|
1285
|
-
|
|
1286
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1287
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1288
|
-
void
|
|
1289
|
-
}
|
|
1290
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToRational))
|
|
1291
|
-
ret
|
|
2032
|
+
WasmI32.toGrain(result): Rational
|
|
1292
2033
|
}
|
|
1293
2034
|
|
|
1294
|
-
|
|
2035
|
+
@unsafe
|
|
2036
|
+
export let coerceNumberToFloat32 = (x: Number) => {
|
|
1295
2037
|
let x = WasmI32.fromGrain(x)
|
|
1296
|
-
let result = if (
|
|
1297
|
-
|
|
2038
|
+
let result = if (
|
|
2039
|
+
!isSimpleNumber(x) &&
|
|
2040
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)
|
|
2041
|
+
) {
|
|
2042
|
+
// avoid extra malloc and prevent x from being freed
|
|
2043
|
+
Memory.incRef(x)
|
|
1298
2044
|
x
|
|
1299
2045
|
} else {
|
|
1300
|
-
|
|
2046
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2047
|
+
Memory.incRef(x)
|
|
2048
|
+
newFloat32(coerceNumberToWasmF32(WasmI32.toGrain(x): Number))
|
|
1301
2049
|
}
|
|
1302
|
-
|
|
1303
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1304
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1305
|
-
void
|
|
1306
|
-
}
|
|
1307
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToFloat32))
|
|
1308
|
-
ret
|
|
2050
|
+
WasmI32.toGrain(result): Float32
|
|
1309
2051
|
}
|
|
1310
2052
|
|
|
1311
|
-
|
|
2053
|
+
@unsafe
|
|
2054
|
+
export let coerceNumberToFloat64 = (x: Number) => {
|
|
1312
2055
|
let x = WasmI32.fromGrain(x)
|
|
1313
|
-
let result = if (
|
|
1314
|
-
|
|
2056
|
+
let result = if (
|
|
2057
|
+
!isSimpleNumber(x) &&
|
|
2058
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
2059
|
+
) {
|
|
2060
|
+
// avoid extra malloc and prevent x from being freed
|
|
2061
|
+
Memory.incRef(x)
|
|
1315
2062
|
x
|
|
1316
2063
|
} else {
|
|
1317
|
-
|
|
2064
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2065
|
+
Memory.incRef(x)
|
|
2066
|
+
newFloat64(coerceNumberToWasmF64(WasmI32.toGrain(x): Number))
|
|
1318
2067
|
}
|
|
1319
|
-
|
|
1320
|
-
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1321
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1322
|
-
void
|
|
1323
|
-
}
|
|
1324
|
-
Memory.decRef(WasmI32.fromGrain(coerceNumberToFloat64))
|
|
1325
|
-
ret
|
|
2068
|
+
WasmI32.toGrain(result): Float64
|
|
1326
2069
|
}
|
|
1327
2070
|
|
|
1328
|
-
|
|
1329
|
-
export let
|
|
1330
|
-
let
|
|
1331
|
-
|
|
1332
|
-
|
|
2071
|
+
@unsafe
|
|
2072
|
+
export let coerceInt32ToNumber = (x: Int32) => {
|
|
2073
|
+
let x = WasmI32.fromGrain(x)
|
|
2074
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2075
|
+
Memory.incRef(x)
|
|
2076
|
+
WasmI32.toGrain(x): Number
|
|
1333
2077
|
}
|
|
1334
2078
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
2079
|
+
@unsafe
|
|
2080
|
+
export let coerceInt64ToNumber = (x: Int64) => {
|
|
2081
|
+
let x = WasmI32.fromGrain(x)
|
|
2082
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2083
|
+
Memory.incRef(x)
|
|
2084
|
+
WasmI32.toGrain(x): Number
|
|
1339
2085
|
}
|
|
1340
2086
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
2087
|
+
@unsafe
|
|
2088
|
+
export let coerceBigIntToNumber = (x: BigInt) => {
|
|
2089
|
+
let x = WasmI32.fromGrain(x)
|
|
2090
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2091
|
+
Memory.incRef(x)
|
|
2092
|
+
WasmI32.toGrain(x): Number
|
|
1345
2093
|
}
|
|
1346
2094
|
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
2095
|
+
@unsafe
|
|
2096
|
+
export let coerceRationalToNumber = (x: Rational) => {
|
|
2097
|
+
let x = WasmI32.fromGrain(x)
|
|
2098
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2099
|
+
Memory.incRef(x)
|
|
2100
|
+
WasmI32.toGrain(x): Number
|
|
1351
2101
|
}
|
|
1352
2102
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
2103
|
+
@unsafe
|
|
2104
|
+
export let coerceFloat32ToNumber = (x: Float32) => {
|
|
2105
|
+
let x = WasmI32.fromGrain(x)
|
|
2106
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2107
|
+
Memory.incRef(x)
|
|
2108
|
+
WasmI32.toGrain(x): Number
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
@unsafe
|
|
2112
|
+
export let coerceFloat64ToNumber = (x: Float64) => {
|
|
2113
|
+
let x = WasmI32.fromGrain(x)
|
|
2114
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2115
|
+
Memory.incRef(x)
|
|
2116
|
+
WasmI32.toGrain(x): Number
|
|
1357
2117
|
}
|
|
1358
2118
|
|
|
1359
2119
|
/// USER-EXPOSED CONVERSION FUNCTIONS
|
|
1360
2120
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
ret
|
|
2121
|
+
@unsafe
|
|
2122
|
+
export let convertExactToInexact = (x: Number) => {
|
|
2123
|
+
x
|
|
1365
2124
|
}
|
|
1366
2125
|
|
|
1367
|
-
|
|
2126
|
+
@unsafe
|
|
2127
|
+
let convertInexactToExactHelp = x => {
|
|
1368
2128
|
if (isSimpleNumber(x)) {
|
|
1369
2129
|
x
|
|
1370
2130
|
} else {
|
|
1371
2131
|
let tag = boxedNumberTag(x)
|
|
1372
|
-
if (
|
|
2132
|
+
if (
|
|
2133
|
+
WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG) ||
|
|
2134
|
+
WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG) ||
|
|
2135
|
+
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) ||
|
|
2136
|
+
WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)
|
|
2137
|
+
) {
|
|
2138
|
+
Memory.incRef(x)
|
|
1373
2139
|
x
|
|
1374
2140
|
} else {
|
|
1375
2141
|
match (tag) {
|
|
1376
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => x,
|
|
1377
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => x,
|
|
1378
|
-
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => x,
|
|
1379
2142
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1380
|
-
|
|
2143
|
+
// TODO(#1191): Investigate if BigInt is more accurate
|
|
2144
|
+
reducedInteger(
|
|
2145
|
+
WasmI64.truncF32S(WasmF32.nearest(boxedFloat32Number(x)))
|
|
2146
|
+
)
|
|
1381
2147
|
},
|
|
1382
2148
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1383
|
-
|
|
2149
|
+
// TODO(#1191): Investigate if BigInt is more accurate
|
|
2150
|
+
reducedInteger(
|
|
2151
|
+
WasmI64.truncF64S(WasmF64.nearest(boxedFloat64Number(x)))
|
|
2152
|
+
)
|
|
1384
2153
|
},
|
|
1385
2154
|
_ => {
|
|
1386
2155
|
throw UnknownNumberTag
|
|
1387
|
-
}
|
|
2156
|
+
},
|
|
1388
2157
|
}
|
|
1389
2158
|
}
|
|
1390
2159
|
}
|
|
1391
2160
|
}
|
|
1392
2161
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
Memory.decRef(WasmI32.fromGrain(x))
|
|
1397
|
-
void
|
|
1398
|
-
}
|
|
1399
|
-
Memory.decRef(WasmI32.fromGrain(convertInexactToExact))
|
|
1400
|
-
ret
|
|
2162
|
+
@unsafe
|
|
2163
|
+
export let convertInexactToExact = (x: Number) => {
|
|
2164
|
+
WasmI32.toGrain(convertInexactToExactHelp(WasmI32.fromGrain(x))): Number
|
|
1401
2165
|
}
|
|
1402
2166
|
|
|
1403
|
-
|
|
2167
|
+
@unsafe
|
|
2168
|
+
export let (+) = (x: Number, y: Number) => {
|
|
1404
2169
|
let x = WasmI32.fromGrain(x)
|
|
1405
2170
|
let y = WasmI32.fromGrain(y)
|
|
1406
|
-
|
|
1407
|
-
Memory.decRef(x)
|
|
1408
|
-
Memory.decRef(y)
|
|
1409
|
-
Memory.decRef(WasmI32.fromGrain((+)))
|
|
1410
|
-
ret
|
|
2171
|
+
numberAdd(x, y)
|
|
1411
2172
|
}
|
|
1412
2173
|
|
|
1413
|
-
|
|
2174
|
+
@unsafe
|
|
2175
|
+
export let (-) = (x: Number, y: Number) => {
|
|
1414
2176
|
let x = WasmI32.fromGrain(x)
|
|
1415
2177
|
let y = WasmI32.fromGrain(y)
|
|
1416
|
-
|
|
1417
|
-
Memory.decRef(x)
|
|
1418
|
-
Memory.decRef(y)
|
|
1419
|
-
Memory.decRef(WasmI32.fromGrain((-)))
|
|
1420
|
-
ret
|
|
2178
|
+
numberSub(x, y)
|
|
1421
2179
|
}
|
|
1422
2180
|
|
|
1423
|
-
|
|
2181
|
+
@unsafe
|
|
2182
|
+
export let (*) = (x: Number, y: Number) => {
|
|
1424
2183
|
let x = WasmI32.fromGrain(x)
|
|
1425
2184
|
let y = WasmI32.fromGrain(y)
|
|
1426
|
-
|
|
1427
|
-
Memory.decRef(x)
|
|
1428
|
-
Memory.decRef(y)
|
|
1429
|
-
Memory.decRef(WasmI32.fromGrain((*)))
|
|
1430
|
-
ret
|
|
2185
|
+
numberTimes(x, y)
|
|
1431
2186
|
}
|
|
1432
2187
|
|
|
1433
|
-
|
|
2188
|
+
@unsafe
|
|
2189
|
+
export let (/) = (x: Number, y: Number) => {
|
|
1434
2190
|
let x = WasmI32.fromGrain(x)
|
|
1435
2191
|
let y = WasmI32.fromGrain(y)
|
|
1436
|
-
|
|
1437
|
-
Memory.decRef(x)
|
|
1438
|
-
Memory.decRef(y)
|
|
1439
|
-
Memory.decRef(WasmI32.fromGrain((/)))
|
|
1440
|
-
ret
|
|
2192
|
+
numberDivide(x, y)
|
|
1441
2193
|
}
|
|
1442
2194
|
|
|
1443
|
-
|
|
2195
|
+
@unsafe
|
|
2196
|
+
export let (%) = (x: Number, y: Number) => {
|
|
1444
2197
|
let x = WasmI32.fromGrain(x)
|
|
1445
2198
|
let y = WasmI32.fromGrain(y)
|
|
1446
|
-
|
|
1447
|
-
Memory.decRef(x)
|
|
1448
|
-
Memory.decRef(y)
|
|
1449
|
-
Memory.decRef(WasmI32.fromGrain((%)))
|
|
1450
|
-
ret
|
|
2199
|
+
WasmI32.toGrain(numberMod(x, y)): Number
|
|
1451
2200
|
}
|
|
1452
2201
|
|
|
1453
2202
|
// inc/dec
|
|
1454
2203
|
|
|
1455
|
-
export let incr =
|
|
1456
|
-
Memory.incRef(WasmI32.fromGrain((+)))
|
|
1457
|
-
// skip incRef on x (to pass through)
|
|
2204
|
+
export let incr = x => {
|
|
1458
2205
|
x + 1
|
|
1459
2206
|
}
|
|
1460
2207
|
|
|
1461
|
-
export let decr =
|
|
1462
|
-
Memory.incRef(WasmI32.fromGrain((-)))
|
|
1463
|
-
// skip incRef on x (to pass through)
|
|
2208
|
+
export let decr = x => {
|
|
1464
2209
|
x - 1
|
|
1465
2210
|
}
|
|
2211
|
+
|
|
2212
|
+
@unsafe
|
|
2213
|
+
export let isBigInt = x => {
|
|
2214
|
+
let x = WasmI32.fromGrain(x)
|
|
2215
|
+
isBigInt(x)
|
|
2216
|
+
}
|