@grain/stdlib 0.5.13 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +201 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +62 -40
- package/hash.md +27 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2071 -0
- package/json.md +646 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +193 -174
- package/runtime/numberUtils.md +29 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +543 -245
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/runtime/numbers.gr
CHANGED
|
@@ -1,124 +1,141 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
@noPervasives
|
|
2
|
+
module Numbers
|
|
3
|
+
|
|
4
|
+
from "runtime/unsafe/memory" include Memory
|
|
5
|
+
from "runtime/unsafe/tags" include Tags
|
|
6
|
+
from "runtime/exception" include Exception
|
|
7
|
+
from "runtime/bigint" include Bigint as BI
|
|
8
|
+
|
|
9
|
+
from "runtime/unsafe/constants" include Constants
|
|
10
|
+
use Constants.{
|
|
11
|
+
_SMIN8_I32,
|
|
12
|
+
_SMAX8_I32,
|
|
13
|
+
_SMIN8_I64,
|
|
14
|
+
_SMAX8_I64,
|
|
15
|
+
_SMIN16_I32,
|
|
16
|
+
_SMAX16_I32,
|
|
17
|
+
_SMIN16_I64,
|
|
18
|
+
_SMAX16_I64,
|
|
19
|
+
_UMAX8_I32,
|
|
20
|
+
_UMAX8_I64,
|
|
21
|
+
_UMAX16_I32,
|
|
22
|
+
_UMAX16_I64,
|
|
9
23
|
_SMAX32_I64 as _I32_MAX,
|
|
10
24
|
_SMIN32_I64 as _I32_MIN,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
_SMAX_I64 as _I64_MAX,
|
|
26
|
+
_SMIN_I64 as _I64_MIN,
|
|
27
|
+
_UMAX32_I64 as _U32_MAX,
|
|
28
|
+
_UMIN32_I64 as _U32_MIN,
|
|
29
|
+
}
|
|
30
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
31
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
32
|
+
from "runtime/unsafe/wasmf32" include WasmF32
|
|
33
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
34
|
+
|
|
35
|
+
primitive (!) = "@not"
|
|
36
|
+
primitive (&&) = "@and"
|
|
37
|
+
primitive (||) = "@or"
|
|
38
|
+
primitive throw = "@throw"
|
|
39
|
+
primitive ignore = "@ignore"
|
|
21
40
|
|
|
22
41
|
exception UnknownNumberTag
|
|
23
42
|
exception InvariantViolation
|
|
24
43
|
|
|
25
|
-
|
|
44
|
+
from "runtime/dataStructures" include DataStructures
|
|
45
|
+
use DataStructures.{
|
|
26
46
|
newRational,
|
|
27
47
|
newInt32,
|
|
28
48
|
newInt64,
|
|
29
49
|
newFloat32,
|
|
30
50
|
newFloat64,
|
|
31
|
-
|
|
51
|
+
tagInt8,
|
|
52
|
+
tagInt16,
|
|
53
|
+
tagUint8,
|
|
54
|
+
tagUint16,
|
|
55
|
+
untagInt8,
|
|
56
|
+
untagInt16,
|
|
57
|
+
untagUint8,
|
|
58
|
+
untagUint16,
|
|
59
|
+
}
|
|
32
60
|
|
|
33
61
|
@unsafe
|
|
34
62
|
let _F32_MAX = 3.40282347e+38W
|
|
35
63
|
@unsafe
|
|
36
64
|
let _F32_MIN = 1.401298464324817e-45W
|
|
37
65
|
@unsafe
|
|
38
|
-
let _F32_MAX_SAFE_INTEGER = 16777215.
|
|
66
|
+
let _F32_MAX_SAFE_INTEGER = 16777215.0w
|
|
39
67
|
@unsafe
|
|
40
|
-
let _F64_MAX_SAFE_INTEGER = 9007199254740991.
|
|
68
|
+
let _F64_MAX_SAFE_INTEGER = 9007199254740991.0W
|
|
41
69
|
|
|
42
|
-
|
|
43
|
-
let (!=) = WasmI32.ne
|
|
70
|
+
use WasmI32.{ (==), (!=), (^), (<<), (>>) }
|
|
44
71
|
|
|
45
72
|
@unsafe
|
|
46
|
-
let tagSimple = x => {
|
|
47
|
-
|
|
73
|
+
provide let tagSimple = x => {
|
|
74
|
+
x << 1n ^ 1n
|
|
48
75
|
}
|
|
49
76
|
|
|
50
77
|
@unsafe
|
|
51
78
|
let untagSimple = x => {
|
|
52
|
-
|
|
79
|
+
x >> 1n
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
@unsafe
|
|
56
83
|
let isSimpleNumber = x => {
|
|
57
|
-
WasmI32.
|
|
58
|
-
|
|
59
|
-
Tags._GRAIN_NUMBER_TAG_TYPE
|
|
60
|
-
)
|
|
84
|
+
use WasmI32.{ (&) }
|
|
85
|
+
(x & Tags._GRAIN_NUMBER_TAG_MASK) == Tags._GRAIN_NUMBER_TAG_TYPE
|
|
61
86
|
}
|
|
62
87
|
|
|
63
88
|
@unsafe
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Tags._GRAIN_GENERIC_HEAP_TAG_TYPE
|
|
69
|
-
)
|
|
70
|
-
) {
|
|
71
|
-
WasmI32.eq(WasmI32.load(x, 0n), Tags._GRAIN_BOXED_NUM_HEAP_TAG)
|
|
89
|
+
provide let isBoxedNumber = x => {
|
|
90
|
+
use WasmI32.{ (&) }
|
|
91
|
+
if ((x & Tags._GRAIN_GENERIC_TAG_MASK) == Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
|
|
92
|
+
WasmI32.load(x, 0n) == Tags._GRAIN_BOXED_NUM_HEAP_TAG
|
|
72
93
|
} else {
|
|
73
94
|
false
|
|
74
95
|
}
|
|
75
96
|
}
|
|
76
97
|
|
|
77
98
|
@unsafe
|
|
78
|
-
|
|
99
|
+
provide let isFloat = x => {
|
|
79
100
|
if (isBoxedNumber(x)) {
|
|
80
101
|
let tag = WasmI32.load(x, 4n)
|
|
81
|
-
|
|
82
|
-
WasmI32.eq(tag, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
102
|
+
tag == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG
|
|
83
103
|
} else {
|
|
84
104
|
false
|
|
85
105
|
}
|
|
86
106
|
}
|
|
87
107
|
|
|
88
108
|
@unsafe
|
|
89
|
-
|
|
109
|
+
provide let isInteger = x => {
|
|
90
110
|
if (isBoxedNumber(x)) {
|
|
91
111
|
let tag = WasmI32.load(x, 4n)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG)
|
|
112
|
+
tag == Tags._GRAIN_INT64_BOXED_NUM_TAG ||
|
|
113
|
+
tag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG
|
|
95
114
|
} else {
|
|
96
115
|
true
|
|
97
116
|
}
|
|
98
117
|
}
|
|
99
118
|
|
|
100
119
|
@unsafe
|
|
101
|
-
|
|
120
|
+
provide let isRational = x => {
|
|
102
121
|
if (isBoxedNumber(x)) {
|
|
103
122
|
let tag = WasmI32.load(x, 4n)
|
|
104
|
-
|
|
123
|
+
tag == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG
|
|
105
124
|
} else {
|
|
106
125
|
false
|
|
107
126
|
}
|
|
108
127
|
}
|
|
109
128
|
|
|
110
129
|
@unsafe
|
|
111
|
-
|
|
130
|
+
provide let isNaN = x => {
|
|
131
|
+
use WasmF64.{ (!=) }
|
|
112
132
|
if (isBoxedNumber(x)) {
|
|
113
|
-
// Boxed numbers can have multiple subtypes, of which
|
|
133
|
+
// Boxed numbers can have multiple subtypes, of which float64 can be NaN.
|
|
114
134
|
let tag = WasmI32.load(x, 4n)
|
|
115
|
-
if (
|
|
135
|
+
if (tag == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) {
|
|
116
136
|
// uses the fact that NaN is the only number not equal to itself
|
|
117
137
|
let wf64 = WasmF64.load(x, 8n)
|
|
118
|
-
|
|
119
|
-
} else if (WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)) {
|
|
120
|
-
let wf32 = WasmF32.load(x, 8n)
|
|
121
|
-
WasmF32.ne(wf32, wf32)
|
|
138
|
+
wf64 != wf64
|
|
122
139
|
} else {
|
|
123
140
|
// Neither rational numbers nor boxed integers can be infinite or NaN.
|
|
124
141
|
// Grain doesn't allow creating a rational with denominator of zero either.
|
|
@@ -134,21 +151,22 @@ export let isNaN = x => {
|
|
|
134
151
|
let isBigInt = x => {
|
|
135
152
|
if (isBoxedNumber(x)) {
|
|
136
153
|
let tag = WasmI32.load(x, 4n)
|
|
137
|
-
|
|
154
|
+
tag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG
|
|
138
155
|
} else {
|
|
139
156
|
false
|
|
140
157
|
}
|
|
141
158
|
}
|
|
142
159
|
|
|
143
160
|
@unsafe
|
|
144
|
-
|
|
161
|
+
provide let isNumber = x => {
|
|
145
162
|
// x is a number if it is a literal number or a boxed_num heap value
|
|
146
163
|
isSimpleNumber(x) || isBoxedNumber(x)
|
|
147
164
|
}
|
|
148
165
|
|
|
149
166
|
@unsafe
|
|
150
167
|
let safeI64toI32 = x => {
|
|
151
|
-
|
|
168
|
+
use WasmI64.{ (<), (>) }
|
|
169
|
+
if (x > _I32_MAX || x < _I32_MIN) {
|
|
152
170
|
throw Exception.Overflow
|
|
153
171
|
} else {
|
|
154
172
|
WasmI32.wrapI64(x)
|
|
@@ -156,48 +174,59 @@ let safeI64toI32 = x => {
|
|
|
156
174
|
}
|
|
157
175
|
|
|
158
176
|
@unsafe
|
|
159
|
-
let i32neg = x =>
|
|
177
|
+
let i32neg = x => {
|
|
178
|
+
use WasmI32.{ (-) }
|
|
179
|
+
0n - x
|
|
180
|
+
}
|
|
160
181
|
|
|
161
182
|
@unsafe
|
|
162
|
-
let i64not = x =>
|
|
183
|
+
let i64not = x => {
|
|
184
|
+
use WasmI64.{ (^) }
|
|
185
|
+
x ^ 0xffffffffffffffffN
|
|
186
|
+
}
|
|
163
187
|
@unsafe
|
|
164
|
-
let i64neg = x =>
|
|
188
|
+
let i64neg = x => {
|
|
189
|
+
use WasmI64.{ (-) }
|
|
190
|
+
0N - x
|
|
191
|
+
}
|
|
165
192
|
|
|
166
193
|
// https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
|
167
194
|
@unsafe
|
|
168
195
|
let rec gcdHelp = (x, y) => {
|
|
169
|
-
|
|
196
|
+
use WasmI64.{ (==), (!=), (&), (-), (<<), (>>), (>) }
|
|
197
|
+
if (x == y || WasmI64.eqz(x)) {
|
|
170
198
|
y
|
|
171
199
|
} else if (WasmI64.eqz(y)) {
|
|
172
200
|
x
|
|
173
|
-
} else if (
|
|
201
|
+
} else if ((i64not(x) & 1N) != 0N) {
|
|
174
202
|
// x is even
|
|
175
|
-
if (
|
|
203
|
+
if ((y & 1N) != 0N) {
|
|
176
204
|
// y is odd
|
|
177
|
-
gcdHelp(
|
|
205
|
+
gcdHelp(x >> 1N, y)
|
|
178
206
|
} else {
|
|
179
|
-
|
|
207
|
+
gcdHelp(x >> 1N, y >> 1N) << 1N
|
|
180
208
|
}
|
|
181
|
-
} else if (
|
|
209
|
+
} else if ((i64not(y) & 1N) != 0N) {
|
|
182
210
|
// y is even and x is odd
|
|
183
|
-
gcdHelp(x,
|
|
184
|
-
} else if (
|
|
185
|
-
gcdHelp(
|
|
211
|
+
gcdHelp(x, y >> 1N)
|
|
212
|
+
} else if (x > y) {
|
|
213
|
+
gcdHelp(x - y, y)
|
|
186
214
|
} else {
|
|
187
|
-
gcdHelp(
|
|
215
|
+
gcdHelp(y - x, x)
|
|
188
216
|
}
|
|
189
217
|
}
|
|
190
218
|
|
|
191
219
|
@unsafe
|
|
192
220
|
let gcd = (x, y) => {
|
|
221
|
+
use WasmI64.{ (<) }
|
|
193
222
|
// Algorithm above breaks on negatives, so
|
|
194
223
|
// we make sure that they are positive at the beginning
|
|
195
|
-
let x = if (
|
|
224
|
+
let x = if (x < 0N) {
|
|
196
225
|
i64neg(x)
|
|
197
226
|
} else {
|
|
198
227
|
x
|
|
199
228
|
}
|
|
200
|
-
let y = if (
|
|
229
|
+
let y = if (y < 0N) {
|
|
201
230
|
i64neg(y)
|
|
202
231
|
} else {
|
|
203
232
|
y
|
|
@@ -211,14 +240,24 @@ let gcd32 = (x, y) => {
|
|
|
211
240
|
}
|
|
212
241
|
|
|
213
242
|
@unsafe
|
|
214
|
-
|
|
215
|
-
|
|
243
|
+
provide let reducedInteger = x => {
|
|
244
|
+
use WasmI64.{ (>>), (<), (>) }
|
|
245
|
+
// TODO(#1736): Remove the formatter ignore when parsing is fixed
|
|
246
|
+
//formatter-ignore
|
|
247
|
+
if (x > (_I32_MAX >> 1N) || x < (_I32_MIN >> 1N)) {
|
|
248
|
+
newInt64(x)
|
|
249
|
+
} else {
|
|
250
|
+
tagSimple(WasmI32.wrapI64(x))
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@unsafe
|
|
255
|
+
provide let reducedUnsignedInteger = x => {
|
|
256
|
+
use WasmI64.{ (>>>) }
|
|
257
|
+
if (WasmI64.gtU(x, _I64_MAX)) {
|
|
258
|
+
BI.makeWrappedUint64(x)
|
|
259
|
+
} else if (WasmI64.gtU(x, _I32_MAX >>> 1N)) {
|
|
216
260
|
newInt64(x)
|
|
217
|
-
} else if (
|
|
218
|
-
WasmI64.gtS(x, WasmI64.shrS(_I32_MAX, 1N)) ||
|
|
219
|
-
WasmI64.ltS(x, WasmI64.shrS(_I32_MIN, 1N))
|
|
220
|
-
) {
|
|
221
|
-
newInt32(WasmI32.wrapI64(x))
|
|
222
261
|
} else {
|
|
223
262
|
tagSimple(WasmI32.wrapI64(x))
|
|
224
263
|
}
|
|
@@ -240,7 +279,7 @@ let reducedBigInteger = x => {
|
|
|
240
279
|
}
|
|
241
280
|
|
|
242
281
|
@unsafe
|
|
243
|
-
let reducedFractionBigInt = (x, y) => {
|
|
282
|
+
let reducedFractionBigInt = (x, y, keepRational) => {
|
|
244
283
|
let mut x = x
|
|
245
284
|
let mut y = y
|
|
246
285
|
let mut needsDecref = false
|
|
@@ -263,7 +302,7 @@ let reducedFractionBigInt = (x, y) => {
|
|
|
263
302
|
let r = WasmI32.load(quotremResult, 4n)
|
|
264
303
|
// free container used to store quotrem result
|
|
265
304
|
Memory.free(quotremResult)
|
|
266
|
-
let ret = if (BI.eqz(r)) {
|
|
305
|
+
let ret = if (!keepRational && BI.eqz(r)) {
|
|
267
306
|
// if remainder is zero, then return the quotient.
|
|
268
307
|
// We decRef the remainder, since we no longer need it
|
|
269
308
|
Memory.decRef(r)
|
|
@@ -290,10 +329,11 @@ let reducedFractionBigInt = (x, y) => {
|
|
|
290
329
|
|
|
291
330
|
@unsafe
|
|
292
331
|
let reducedFraction64 = (x, y) => {
|
|
332
|
+
use WasmI64.{ (/), (<) }
|
|
293
333
|
let mut x = x
|
|
294
334
|
let mut y = y
|
|
295
335
|
|
|
296
|
-
if (
|
|
336
|
+
if (y < 0N) {
|
|
297
337
|
// Normalization 1: Never do negative/negative
|
|
298
338
|
// Normalization 2: Never allow a negative denominator
|
|
299
339
|
x = i64neg(x)
|
|
@@ -303,11 +343,11 @@ let reducedFraction64 = (x, y) => {
|
|
|
303
343
|
throw Exception.DivisionByZero
|
|
304
344
|
}
|
|
305
345
|
if (WasmI64.eqz(WasmI64.remS(x, y))) {
|
|
306
|
-
reducedInteger(
|
|
346
|
+
reducedInteger(x / y)
|
|
307
347
|
} else {
|
|
308
348
|
let factor = gcd(x, y)
|
|
309
|
-
let xdiv =
|
|
310
|
-
let ydiv =
|
|
349
|
+
let xdiv = x / factor
|
|
350
|
+
let ydiv = y / factor
|
|
311
351
|
newRational(BI.makeWrappedInt64(xdiv), BI.makeWrappedInt64(ydiv))
|
|
312
352
|
}
|
|
313
353
|
}
|
|
@@ -336,69 +376,53 @@ let reducedFraction64 = (x, y) => {
|
|
|
336
376
|
*/
|
|
337
377
|
|
|
338
378
|
@unsafe
|
|
339
|
-
|
|
379
|
+
provide let boxedNumberTag = xptr => {
|
|
340
380
|
WasmI32.load(xptr, 4n)
|
|
341
381
|
}
|
|
342
382
|
|
|
343
383
|
@unsafe
|
|
344
|
-
|
|
345
|
-
WasmI32.load(xptr, 8n)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
@unsafe
|
|
349
|
-
export let boxedInt64Number = xptr => {
|
|
384
|
+
provide let boxedInt64Number = xptr => {
|
|
350
385
|
WasmI64.load(xptr, 8n)
|
|
351
386
|
}
|
|
352
387
|
|
|
353
388
|
@unsafe
|
|
354
|
-
|
|
355
|
-
WasmF32.load(xptr, 8n)
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
@unsafe
|
|
359
|
-
export let boxedFloat64Number = xptr => {
|
|
389
|
+
provide let boxedFloat64Number = xptr => {
|
|
360
390
|
WasmF64.load(xptr, 8n)
|
|
361
391
|
}
|
|
362
392
|
|
|
363
393
|
@unsafe
|
|
364
|
-
|
|
394
|
+
provide let boxedRationalNumerator = xptr => {
|
|
365
395
|
WasmI32.load(xptr, 8n)
|
|
366
396
|
}
|
|
367
397
|
|
|
368
398
|
@unsafe
|
|
369
|
-
|
|
399
|
+
provide let boxedRationalDenominator = xptr => {
|
|
370
400
|
WasmI32.load(xptr, 12n)
|
|
371
401
|
}
|
|
372
402
|
|
|
373
403
|
@unsafe
|
|
374
|
-
|
|
404
|
+
provide let coerceNumberToWasmF32 = (x: Number) => {
|
|
375
405
|
let x = WasmI32.fromGrain(x)
|
|
376
406
|
if (isSimpleNumber(x)) {
|
|
377
407
|
WasmF32.convertI32S(untagSimple(x))
|
|
378
408
|
} else {
|
|
379
409
|
let xtag = boxedNumberTag(x)
|
|
380
410
|
match (xtag) {
|
|
381
|
-
t when
|
|
382
|
-
WasmF32.convertI32S(boxedInt32Number(x))
|
|
383
|
-
},
|
|
384
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
411
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
385
412
|
WasmF32.convertI64S(boxedInt64Number(x))
|
|
386
413
|
},
|
|
387
|
-
t when
|
|
414
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
388
415
|
BI.toFloat32(x)
|
|
389
416
|
},
|
|
390
|
-
t when
|
|
391
|
-
WasmF32.
|
|
392
|
-
|
|
417
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
418
|
+
use WasmF32.{ (/) }
|
|
419
|
+
BI.toFloat32(boxedRationalNumerator(x)) /
|
|
393
420
|
BI.toFloat32(boxedRationalDenominator(x))
|
|
394
|
-
)
|
|
395
421
|
},
|
|
396
|
-
t when
|
|
397
|
-
|
|
398
|
-
},
|
|
399
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
422
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
423
|
+
use WasmF64.{ (<), (>) }
|
|
400
424
|
let xval = boxedFloat64Number(x)
|
|
401
|
-
if (
|
|
425
|
+
if (xval > _F32_MAX || xval < _F32_MIN) {
|
|
402
426
|
// Not an actual return value
|
|
403
427
|
throw Exception.Overflow
|
|
404
428
|
} else {
|
|
@@ -413,32 +437,25 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
413
437
|
}
|
|
414
438
|
|
|
415
439
|
@unsafe
|
|
416
|
-
|
|
440
|
+
provide let coerceNumberToWasmF64 = (x: Number) => {
|
|
417
441
|
let x = WasmI32.fromGrain(x)
|
|
418
442
|
if (isSimpleNumber(x)) {
|
|
419
443
|
WasmF64.convertI32S(untagSimple(x))
|
|
420
444
|
} else {
|
|
421
445
|
let xtag = boxedNumberTag(x)
|
|
422
446
|
match (xtag) {
|
|
423
|
-
t when
|
|
424
|
-
WasmF64.convertI32S(boxedInt32Number(x))
|
|
425
|
-
},
|
|
426
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
447
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
427
448
|
WasmF64.convertI64S(boxedInt64Number(x))
|
|
428
449
|
},
|
|
429
|
-
t when
|
|
450
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
430
451
|
BI.toFloat64(x)
|
|
431
452
|
},
|
|
432
|
-
t when
|
|
433
|
-
WasmF64.
|
|
434
|
-
|
|
453
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
454
|
+
use WasmF64.{ (/) }
|
|
455
|
+
BI.toFloat64(boxedRationalNumerator(x)) /
|
|
435
456
|
BI.toFloat64(boxedRationalDenominator(x))
|
|
436
|
-
)
|
|
437
|
-
},
|
|
438
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
439
|
-
WasmF64.promoteF32(boxedFloat32Number(x))
|
|
440
457
|
},
|
|
441
|
-
t when
|
|
458
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
442
459
|
boxedFloat64Number(x)
|
|
443
460
|
},
|
|
444
461
|
_ => {
|
|
@@ -449,20 +466,17 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
@unsafe
|
|
452
|
-
|
|
469
|
+
provide let coerceNumberToWasmI64 = (x: Number) => {
|
|
453
470
|
let x = WasmI32.fromGrain(x)
|
|
454
471
|
if (isSimpleNumber(x)) {
|
|
455
472
|
WasmI64.extendI32S(untagSimple(x))
|
|
456
473
|
} else {
|
|
457
474
|
let xtag = boxedNumberTag(x)
|
|
458
475
|
match (xtag) {
|
|
459
|
-
t when
|
|
460
|
-
WasmI64.extendI32S(boxedInt32Number(x))
|
|
461
|
-
},
|
|
462
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
476
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
463
477
|
boxedInt64Number(x)
|
|
464
478
|
},
|
|
465
|
-
t when
|
|
479
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
466
480
|
BI.toInt64(x)
|
|
467
481
|
},
|
|
468
482
|
_ => {
|
|
@@ -474,24 +488,86 @@ export let coerceNumberToWasmI64 = (x: Number) => {
|
|
|
474
488
|
}
|
|
475
489
|
|
|
476
490
|
@unsafe
|
|
477
|
-
|
|
491
|
+
provide let coerceNumberToWasmI32 = (x: Number) => {
|
|
492
|
+
use WasmI64.{ (<), (>) }
|
|
478
493
|
let x = WasmI32.fromGrain(x)
|
|
479
494
|
if (isSimpleNumber(x)) {
|
|
480
495
|
untagSimple(x)
|
|
481
496
|
} else {
|
|
482
497
|
let xtag = boxedNumberTag(x)
|
|
483
498
|
match (xtag) {
|
|
484
|
-
t when
|
|
485
|
-
|
|
499
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
500
|
+
let int64 = boxedInt64Number(x)
|
|
501
|
+
if (int64 > _I32_MAX || int64 < _I32_MIN) {
|
|
502
|
+
throw Exception.Overflow
|
|
503
|
+
}
|
|
504
|
+
WasmI32.wrapI64(int64)
|
|
505
|
+
},
|
|
506
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
507
|
+
BI.toInt32(x)
|
|
508
|
+
},
|
|
509
|
+
_ => {
|
|
510
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
511
|
+
throw Exception.NumberNotIntlike
|
|
512
|
+
},
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
@unsafe
|
|
518
|
+
provide let coerceNumberToUnsignedWasmI64 = (x: Number) => {
|
|
519
|
+
use WasmI32.{ (<) }
|
|
520
|
+
let x = WasmI32.fromGrain(x)
|
|
521
|
+
if (isSimpleNumber(x)) {
|
|
522
|
+
let num = untagSimple(x)
|
|
523
|
+
if (num < 0n) {
|
|
524
|
+
throw Exception.Overflow
|
|
525
|
+
}
|
|
526
|
+
WasmI64.extendI32U(num)
|
|
527
|
+
} else {
|
|
528
|
+
let xtag = boxedNumberTag(x)
|
|
529
|
+
match (xtag) {
|
|
530
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
531
|
+
use WasmI64.{ (<) }
|
|
532
|
+
let int64 = boxedInt64Number(x)
|
|
533
|
+
if (int64 < 0N) {
|
|
534
|
+
throw Exception.Overflow
|
|
535
|
+
}
|
|
536
|
+
int64
|
|
537
|
+
},
|
|
538
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
539
|
+
BI.toUnsignedInt64(x)
|
|
540
|
+
},
|
|
541
|
+
_ => {
|
|
542
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
543
|
+
throw Exception.NumberNotIntlike
|
|
486
544
|
},
|
|
487
|
-
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
@unsafe
|
|
550
|
+
provide let coerceNumberToUnsignedWasmI32 = (x: Number) => {
|
|
551
|
+
use WasmI32.{ (<) }
|
|
552
|
+
let x = WasmI32.fromGrain(x)
|
|
553
|
+
if (isSimpleNumber(x)) {
|
|
554
|
+
let num = untagSimple(x)
|
|
555
|
+
if (num < 0n) {
|
|
556
|
+
throw Exception.Overflow
|
|
557
|
+
}
|
|
558
|
+
num
|
|
559
|
+
} else {
|
|
560
|
+
let xtag = boxedNumberTag(x)
|
|
561
|
+
match (xtag) {
|
|
562
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
563
|
+
use WasmI64.{ (<), (>) }
|
|
488
564
|
let int64 = boxedInt64Number(x)
|
|
489
|
-
if (
|
|
565
|
+
if (int64 > _U32_MAX || int64 < _U32_MIN) {
|
|
490
566
|
throw Exception.Overflow
|
|
491
567
|
}
|
|
492
568
|
WasmI32.wrapI64(int64)
|
|
493
569
|
},
|
|
494
|
-
t when
|
|
570
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
495
571
|
BI.toInt32(x)
|
|
496
572
|
},
|
|
497
573
|
_ => {
|
|
@@ -503,20 +579,17 @@ export let coerceNumberToWasmI32 = (x: Number) => {
|
|
|
503
579
|
}
|
|
504
580
|
|
|
505
581
|
@unsafe
|
|
506
|
-
|
|
582
|
+
let coerceNumberToBigInt = (x: Number) => {
|
|
507
583
|
let x = WasmI32.fromGrain(x)
|
|
508
584
|
if (isSimpleNumber(x)) {
|
|
509
585
|
BI.makeWrappedInt32(untagSimple(x))
|
|
510
586
|
} else {
|
|
511
587
|
let xtag = boxedNumberTag(x)
|
|
512
588
|
match (xtag) {
|
|
513
|
-
t when
|
|
514
|
-
BI.makeWrappedInt32(boxedInt32Number(x))
|
|
515
|
-
},
|
|
516
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
589
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
517
590
|
BI.makeWrappedInt64(boxedInt64Number(x))
|
|
518
591
|
},
|
|
519
|
-
t when
|
|
592
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
520
593
|
Memory.incRef(x)
|
|
521
594
|
x
|
|
522
595
|
},
|
|
@@ -530,24 +603,26 @@ export let coerceNumberToBigInt = (x: Number) => {
|
|
|
530
603
|
|
|
531
604
|
@unsafe
|
|
532
605
|
let isIntegerF32 = value => {
|
|
533
|
-
WasmF32.
|
|
606
|
+
use WasmF32.{ (==) }
|
|
607
|
+
value == WasmF32.trunc(value)
|
|
534
608
|
}
|
|
535
609
|
|
|
536
610
|
@unsafe
|
|
537
611
|
let isIntegerF64 = value => {
|
|
538
|
-
WasmF64.
|
|
612
|
+
use WasmF64.{ (==) }
|
|
613
|
+
value == WasmF64.trunc(value)
|
|
539
614
|
}
|
|
540
615
|
|
|
541
616
|
@unsafe
|
|
542
617
|
let isSafeIntegerF32 = value => {
|
|
543
|
-
WasmF32.
|
|
544
|
-
|
|
618
|
+
use WasmF32.{ (==), (<=) }
|
|
619
|
+
WasmF32.abs(value) <= _F32_MAX_SAFE_INTEGER && WasmF32.trunc(value) == value
|
|
545
620
|
}
|
|
546
621
|
|
|
547
622
|
@unsafe
|
|
548
623
|
let isSafeIntegerF64 = value => {
|
|
549
|
-
WasmF64.
|
|
550
|
-
|
|
624
|
+
use WasmF64.{ (==), (<=) }
|
|
625
|
+
WasmF64.abs(value) <= _F64_MAX_SAFE_INTEGER && WasmF64.trunc(value) == value
|
|
551
626
|
}
|
|
552
627
|
|
|
553
628
|
/** Number-aware equality checking
|
|
@@ -556,9 +631,8 @@ let isSafeIntegerF64 = value => {
|
|
|
556
631
|
* to that number
|
|
557
632
|
*
|
|
558
633
|
* NOTE: The preconditions in these functions are important, so do NOT
|
|
559
|
-
*
|
|
634
|
+
* provide them!
|
|
560
635
|
*/
|
|
561
|
-
|
|
562
636
|
@unsafe
|
|
563
637
|
let numberEqualSimpleHelp = (x, y) => {
|
|
564
638
|
// PRECONDITION: x is a "simple" number (value tag is 0) and x !== y and isNumber(y)
|
|
@@ -569,30 +643,22 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
569
643
|
let xval = untagSimple(x) // <- actual int value of x
|
|
570
644
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
571
645
|
match (yBoxedNumberTag) {
|
|
572
|
-
t when
|
|
573
|
-
|
|
574
|
-
WasmI32.eq(xval, yBoxedVal)
|
|
575
|
-
},
|
|
576
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
646
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
647
|
+
use WasmI64.{ (==) }
|
|
577
648
|
let yBoxedVal = boxedInt64Number(y)
|
|
578
|
-
WasmI64.
|
|
649
|
+
WasmI64.extendI32S(xval) == yBoxedVal
|
|
579
650
|
},
|
|
580
|
-
t when
|
|
651
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
581
652
|
WasmI32.eqz(BI.cmpI64(y, WasmI64.extendI32S(xval)))
|
|
582
653
|
},
|
|
583
|
-
t when
|
|
654
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
584
655
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
585
656
|
false
|
|
586
657
|
},
|
|
587
|
-
t when
|
|
588
|
-
|
|
589
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
590
|
-
WasmF32.eq(WasmF32.convertI32S(xval), yBoxedVal)
|
|
591
|
-
},
|
|
592
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
658
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
659
|
+
use WasmF64.{ (==) }
|
|
593
660
|
let yBoxedVal = boxedFloat64Number(y)
|
|
594
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
595
|
-
WasmF64.eq(WasmF64.convertI32S(xval), yBoxedVal)
|
|
661
|
+
isSafeIntegerF64(yBoxedVal) && WasmF64.convertI32S(xval) == yBoxedVal
|
|
596
662
|
},
|
|
597
663
|
_ => {
|
|
598
664
|
throw UnknownNumberTag
|
|
@@ -606,35 +672,28 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
606
672
|
// PRECONDITION: x !== y and isNumber(y)
|
|
607
673
|
// Basic number:
|
|
608
674
|
if (isSimpleNumber(y)) {
|
|
609
|
-
WasmI64.
|
|
675
|
+
use WasmI64.{ (==) }
|
|
676
|
+
xBoxedVal == WasmI64.extendI32S(untagSimple(y))
|
|
610
677
|
} else {
|
|
611
678
|
// Boxed number:
|
|
612
679
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
613
680
|
match (yBoxedNumberTag) {
|
|
614
|
-
t when
|
|
615
|
-
|
|
616
|
-
WasmI64.eq(xBoxedVal, WasmI64.extendI32S(yBoxedVal))
|
|
617
|
-
},
|
|
618
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
681
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
682
|
+
use WasmI64.{ (==) }
|
|
619
683
|
let yBoxedVal = boxedInt64Number(y)
|
|
620
|
-
|
|
684
|
+
xBoxedVal == yBoxedVal
|
|
621
685
|
},
|
|
622
|
-
t when
|
|
686
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
623
687
|
WasmI32.eqz(BI.cmpI64(y, xBoxedVal))
|
|
624
688
|
},
|
|
625
|
-
t when
|
|
689
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
626
690
|
// NOTE: we always store in most reduced form, so a rational and an int are never equal
|
|
627
691
|
false
|
|
628
692
|
},
|
|
629
|
-
t when
|
|
630
|
-
|
|
631
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
632
|
-
WasmI64.eq(xBoxedVal, WasmI64.truncF32S(yBoxedVal))
|
|
633
|
-
},
|
|
634
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
693
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
694
|
+
use WasmI64.{ (==) }
|
|
635
695
|
let yBoxedVal = boxedFloat64Number(y)
|
|
636
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
637
|
-
WasmI64.eq(xBoxedVal, WasmI64.truncF64S(yBoxedVal))
|
|
696
|
+
isSafeIntegerF64(yBoxedVal) && xBoxedVal == WasmI64.truncF64S(yBoxedVal)
|
|
638
697
|
},
|
|
639
698
|
_ => {
|
|
640
699
|
throw UnknownNumberTag
|
|
@@ -643,12 +702,6 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
643
702
|
}
|
|
644
703
|
}
|
|
645
704
|
|
|
646
|
-
@unsafe
|
|
647
|
-
let numberEqualInt32Help = (xBoxedVal, y) => {
|
|
648
|
-
// We can just pretend it's 64-bit for the equality check
|
|
649
|
-
numberEqualInt64Help(WasmI64.extendI32S(xBoxedVal), y)
|
|
650
|
-
}
|
|
651
|
-
|
|
652
705
|
@unsafe
|
|
653
706
|
let numberEqualRationalHelp = (xptr, y) => {
|
|
654
707
|
// PRECONDITION: x is rational and x !== y and isNumber(y)
|
|
@@ -661,37 +714,23 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
661
714
|
// Boxed number:
|
|
662
715
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
663
716
|
match (yBoxedNumberTag) {
|
|
664
|
-
t when
|
|
665
|
-
false
|
|
666
|
-
},
|
|
667
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
717
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
668
718
|
false
|
|
669
719
|
},
|
|
670
|
-
t when
|
|
720
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
671
721
|
false
|
|
672
722
|
},
|
|
673
|
-
t when
|
|
723
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
674
724
|
let yNumerator = boxedRationalNumerator(y)
|
|
675
725
|
let yDenominator = boxedRationalDenominator(y)
|
|
676
726
|
BI.eq(xNumerator, yNumerator) && BI.eq(xDenominator, yDenominator)
|
|
677
727
|
},
|
|
678
|
-
t when
|
|
679
|
-
|
|
680
|
-
let xAsFloat = WasmF32.div(
|
|
681
|
-
BI.toFloat32(xNumerator),
|
|
682
|
-
BI.toFloat32(xDenominator)
|
|
683
|
-
)
|
|
684
|
-
// TODO(#303): maybe we should have some sort of tolerance?
|
|
685
|
-
WasmF32.eq(xAsFloat, yBoxedVal)
|
|
686
|
-
},
|
|
687
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
728
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
729
|
+
use WasmF64.{ (==), (/) }
|
|
688
730
|
let yBoxedVal = boxedFloat64Number(y)
|
|
689
|
-
let xAsFloat =
|
|
690
|
-
BI.toFloat64(xNumerator),
|
|
691
|
-
BI.toFloat64(xDenominator)
|
|
692
|
-
)
|
|
731
|
+
let xAsFloat = BI.toFloat64(xNumerator) / BI.toFloat64(xDenominator)
|
|
693
732
|
// TODO(#303): maybe we should have some sort of tolerance?
|
|
694
|
-
|
|
733
|
+
xAsFloat == yBoxedVal
|
|
695
734
|
},
|
|
696
735
|
_ => {
|
|
697
736
|
throw UnknownNumberTag
|
|
@@ -705,40 +744,32 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
705
744
|
let xIsInteger = isIntegerF64(x)
|
|
706
745
|
// Basic number:
|
|
707
746
|
if (isSimpleNumber(y)) {
|
|
708
|
-
|
|
747
|
+
use WasmF64.{ (==) }
|
|
748
|
+
xIsInteger && x == WasmF64.convertI32S(untagSimple(y))
|
|
709
749
|
} else {
|
|
710
750
|
// Boxed number
|
|
711
751
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
712
752
|
match (yBoxedNumberTag) {
|
|
713
|
-
t when
|
|
714
|
-
|
|
715
|
-
isSafeIntegerF64(x) && WasmF64.eq(x, WasmF64.convertI32S(yBoxedVal))
|
|
716
|
-
},
|
|
717
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
753
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
754
|
+
use WasmF64.{ (==) }
|
|
718
755
|
let yBoxedVal = boxedInt64Number(y)
|
|
719
|
-
isSafeIntegerF64(x) &&
|
|
756
|
+
isSafeIntegerF64(x) && x == WasmF64.convertI64S(yBoxedVal)
|
|
720
757
|
},
|
|
721
|
-
t when
|
|
758
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
722
759
|
WasmI32.eqz(BI.cmpF64(y, x))
|
|
723
760
|
},
|
|
724
|
-
t when
|
|
761
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
762
|
+
use WasmF64.{ (==), (/) }
|
|
725
763
|
let yNumerator = boxedRationalNumerator(y)
|
|
726
764
|
let yDenominator = boxedRationalDenominator(y)
|
|
727
|
-
let yAsFloat =
|
|
728
|
-
|
|
729
|
-
BI.toFloat64(yDenominator)
|
|
730
|
-
)
|
|
731
|
-
WasmF64.eq(x, yAsFloat)
|
|
732
|
-
},
|
|
733
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
734
|
-
let yBoxedVal = boxedFloat32Number(y)
|
|
735
|
-
// TODO(#303): maybe we should have some sort of tolerance?
|
|
736
|
-
WasmF64.eq(x, WasmF64.promoteF32(yBoxedVal))
|
|
765
|
+
let yAsFloat = BI.toFloat64(yNumerator) / BI.toFloat64(yDenominator)
|
|
766
|
+
x == yAsFloat
|
|
737
767
|
},
|
|
738
|
-
t when
|
|
768
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
769
|
+
use WasmF64.{ (==) }
|
|
739
770
|
let yBoxedVal = boxedFloat64Number(y)
|
|
740
771
|
// TODO(#303): maybe we should have some sort of tolerance?
|
|
741
|
-
|
|
772
|
+
x == yBoxedVal
|
|
742
773
|
},
|
|
743
774
|
_ => {
|
|
744
775
|
throw UnknownNumberTag
|
|
@@ -747,27 +778,6 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
747
778
|
}
|
|
748
779
|
}
|
|
749
780
|
|
|
750
|
-
@unsafe
|
|
751
|
-
let numberEqualFloat32Help = (x, y) => {
|
|
752
|
-
let xIsInteger = isIntegerF32(x)
|
|
753
|
-
// Basic number:
|
|
754
|
-
if (isSimpleNumber(y)) {
|
|
755
|
-
xIsInteger && WasmF32.eq(x, WasmF32.convertI32S(untagSimple(y)))
|
|
756
|
-
} else {
|
|
757
|
-
// Boxed number
|
|
758
|
-
let yBoxedNumberTag = boxedNumberTag(y)
|
|
759
|
-
match (yBoxedNumberTag) {
|
|
760
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
761
|
-
// Special case: f32/f32 equality (need to handle here without promotion)
|
|
762
|
-
WasmF32.eq(x, boxedFloat32Number(y))
|
|
763
|
-
},
|
|
764
|
-
_ => {
|
|
765
|
-
numberEqualFloat64Help(WasmF64.promoteF32(x), y)
|
|
766
|
-
},
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
|
|
771
781
|
@unsafe
|
|
772
782
|
let numberEqualBigIntHelp = (x, y) => {
|
|
773
783
|
if (isSimpleNumber(y)) {
|
|
@@ -776,26 +786,18 @@ let numberEqualBigIntHelp = (x, y) => {
|
|
|
776
786
|
// Boxed number
|
|
777
787
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
778
788
|
match (yBoxedNumberTag) {
|
|
779
|
-
t when
|
|
780
|
-
let yBoxedVal = boxedInt32Number(y)
|
|
781
|
-
WasmI32.eqz(BI.cmpI64(x, WasmI64.extendI32S(yBoxedVal)))
|
|
782
|
-
},
|
|
783
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
789
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
784
790
|
let yBoxedVal = boxedInt64Number(y)
|
|
785
791
|
WasmI32.eqz(BI.cmpI64(x, yBoxedVal))
|
|
786
792
|
},
|
|
787
|
-
t when
|
|
793
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
788
794
|
BI.eq(x, y)
|
|
789
795
|
},
|
|
790
|
-
t when
|
|
796
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
791
797
|
// Rationals are reduced, so it must be unequal
|
|
792
798
|
false
|
|
793
799
|
},
|
|
794
|
-
t when
|
|
795
|
-
let yBoxedVal = boxedFloat32Number(y)
|
|
796
|
-
WasmI32.eqz(BI.cmpF32(x, yBoxedVal))
|
|
797
|
-
},
|
|
798
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
800
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
799
801
|
let yBoxedVal = boxedFloat64Number(y)
|
|
800
802
|
WasmI32.eqz(BI.cmpF64(x, yBoxedVal))
|
|
801
803
|
},
|
|
@@ -807,32 +809,25 @@ let numberEqualBigIntHelp = (x, y) => {
|
|
|
807
809
|
}
|
|
808
810
|
|
|
809
811
|
@unsafe
|
|
810
|
-
|
|
812
|
+
provide let numberEqual = (x, y) => {
|
|
811
813
|
if (isSimpleNumber(x)) {
|
|
812
814
|
// Short circuit if non-pointer value is the same
|
|
813
|
-
|
|
815
|
+
x == y || numberEqualSimpleHelp(x, y)
|
|
814
816
|
} else {
|
|
815
817
|
// Boxed number
|
|
816
818
|
let xBoxedNumberTag = boxedNumberTag(x)
|
|
817
819
|
match (xBoxedNumberTag) {
|
|
818
|
-
t when
|
|
819
|
-
let xBoxedVal = boxedInt32Number(x)
|
|
820
|
-
numberEqualInt32Help(xBoxedVal, y)
|
|
821
|
-
},
|
|
822
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
820
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
823
821
|
let xBoxedVal = boxedInt64Number(x)
|
|
824
822
|
numberEqualInt64Help(xBoxedVal, y)
|
|
825
823
|
},
|
|
826
|
-
t when
|
|
824
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
827
825
|
numberEqualRationalHelp(x, y)
|
|
828
826
|
},
|
|
829
|
-
t when
|
|
830
|
-
numberEqualFloat32Help(boxedFloat32Number(x), y)
|
|
831
|
-
},
|
|
832
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
827
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
833
828
|
numberEqualFloat64Help(boxedFloat64Number(x), y)
|
|
834
829
|
},
|
|
835
|
-
t when
|
|
830
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
836
831
|
numberEqualBigIntHelp(x, y)
|
|
837
832
|
},
|
|
838
833
|
_ => {
|
|
@@ -849,37 +844,29 @@ export let numberEqual = (x, y) => {
|
|
|
849
844
|
|
|
850
845
|
@unsafe
|
|
851
846
|
let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
847
|
+
use WasmI64.{ (+), (-) }
|
|
852
848
|
// PRECONDITION: x is a "simple" number (value tag is 0) and isNumber(y)
|
|
853
849
|
if (isSimpleNumber(y)) {
|
|
854
850
|
let x = WasmI64.extendI32S(untagSimple(x))
|
|
855
851
|
let y = WasmI64.extendI32S(untagSimple(y))
|
|
856
852
|
let result = if (isSub) {
|
|
857
|
-
|
|
853
|
+
x - y
|
|
858
854
|
} else {
|
|
859
|
-
|
|
855
|
+
x + y
|
|
860
856
|
}
|
|
861
857
|
reducedInteger(result)
|
|
862
858
|
} else {
|
|
863
859
|
let xval = untagSimple(x) // <- actual int value of x
|
|
864
860
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
865
861
|
match (yBoxedNumberTag) {
|
|
866
|
-
t when
|
|
867
|
-
|
|
868
|
-
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
869
|
-
let result =
|
|
870
|
-
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
871
|
-
else WasmI64.add(xval, yBoxedVal)
|
|
872
|
-
reducedInteger(result)
|
|
873
|
-
},
|
|
874
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
862
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
863
|
+
use WasmI64.{ (<), (>), (>=) }
|
|
875
864
|
let yBoxedVal = boxedInt64Number(y)
|
|
876
865
|
let xval64 = WasmI64.extendI32S(xval)
|
|
877
|
-
let result =
|
|
878
|
-
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
879
|
-
else WasmI64.add(xval64, yBoxedVal)
|
|
866
|
+
let result = if (isSub) xval64 - yBoxedVal else xval64 + yBoxedVal
|
|
880
867
|
if (
|
|
881
|
-
|
|
882
|
-
|
|
868
|
+
yBoxedVal >= 0N && result < xval64 ||
|
|
869
|
+
yBoxedVal < 0N && result > xval64
|
|
883
870
|
) {
|
|
884
871
|
// Overflow. Promote to BigInt
|
|
885
872
|
let xBig = BI.makeWrappedInt32(xval)
|
|
@@ -896,41 +883,33 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
896
883
|
reducedInteger(result)
|
|
897
884
|
}
|
|
898
885
|
},
|
|
899
|
-
t when
|
|
886
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
900
887
|
// Promote x to bigint and do operation
|
|
901
888
|
let xBig = BI.makeWrappedInt32(xval)
|
|
902
889
|
let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
|
|
903
890
|
Memory.decRef(xBig)
|
|
904
891
|
reducedBigInteger(result)
|
|
905
892
|
},
|
|
906
|
-
t when
|
|
893
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
907
894
|
let xBig = BI.makeWrappedInt32(xval)
|
|
908
895
|
let yNumerator = boxedRationalNumerator(y)
|
|
909
896
|
let yDenominator = boxedRationalDenominator(y)
|
|
910
897
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
911
898
|
Memory.decRef(xBig)
|
|
912
|
-
let result =
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
899
|
+
let result = if (isSub)
|
|
900
|
+
BI.sub(expandedXNumerator, yNumerator)
|
|
901
|
+
else
|
|
902
|
+
BI.add(expandedXNumerator, yNumerator)
|
|
903
|
+
let ret = reducedFractionBigInt(result, yDenominator, false)
|
|
916
904
|
Memory.decRef(expandedXNumerator)
|
|
917
905
|
Memory.decRef(result)
|
|
918
906
|
ret
|
|
919
907
|
},
|
|
920
|
-
t when
|
|
921
|
-
|
|
922
|
-
let xval = WasmF32.convertI32S(xval)
|
|
923
|
-
let result =
|
|
924
|
-
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
925
|
-
else WasmF32.add(xval, yBoxedVal)
|
|
926
|
-
newFloat32(result)
|
|
927
|
-
},
|
|
928
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
908
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
909
|
+
use WasmF64.{ (+), (-) }
|
|
929
910
|
let yBoxedVal = boxedFloat64Number(y)
|
|
930
911
|
let xval = WasmF64.convertI32S(xval)
|
|
931
|
-
let result =
|
|
932
|
-
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
933
|
-
else WasmF64.add(xval, yBoxedVal)
|
|
912
|
+
let result = if (isSub) xval - yBoxedVal else xval + yBoxedVal
|
|
934
913
|
newFloat64(result)
|
|
935
914
|
},
|
|
936
915
|
_ => {
|
|
@@ -942,13 +921,11 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
942
921
|
|
|
943
922
|
@unsafe
|
|
944
923
|
let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
924
|
+
use WasmI64.{ (+), (-), (<), (>), (>), (>=) }
|
|
945
925
|
if (isSimpleNumber(y)) {
|
|
946
926
|
let yval = WasmI64.extendI32S(untagSimple(y))
|
|
947
|
-
let result = if (isSub)
|
|
948
|
-
if (
|
|
949
|
-
WasmI64.geS(yval, 0N) && WasmI64.ltS(result, xval) ||
|
|
950
|
-
WasmI64.ltS(yval, 0N) && WasmI64.gtS(result, xval)
|
|
951
|
-
) {
|
|
927
|
+
let result = if (isSub) xval - yval else xval + yval
|
|
928
|
+
if (yval >= 0N && result < xval || yval < 0N && result > xval) {
|
|
952
929
|
// Overflow. Promote to BigInt
|
|
953
930
|
let xBig = BI.makeWrappedInt64(xval)
|
|
954
931
|
let yBig = BI.makeWrappedInt64(yval)
|
|
@@ -966,22 +943,13 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
966
943
|
} else {
|
|
967
944
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
968
945
|
match (yBoxedNumberTag) {
|
|
969
|
-
t when
|
|
970
|
-
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
971
|
-
let result =
|
|
972
|
-
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
973
|
-
else WasmI64.add(xval, yBoxedVal)
|
|
974
|
-
reducedInteger(result)
|
|
975
|
-
},
|
|
976
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
946
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
977
947
|
let yBoxedVal = boxedInt64Number(y)
|
|
978
948
|
let xval64 = xval
|
|
979
|
-
let result =
|
|
980
|
-
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
981
|
-
else WasmI64.add(xval64, yBoxedVal)
|
|
949
|
+
let result = if (isSub) xval64 - yBoxedVal else xval64 + yBoxedVal
|
|
982
950
|
if (
|
|
983
|
-
|
|
984
|
-
|
|
951
|
+
yBoxedVal >= 0N && result < xval64 ||
|
|
952
|
+
yBoxedVal < 0N && result > xval64
|
|
985
953
|
) {
|
|
986
954
|
// Overflow. Promote to BigInt
|
|
987
955
|
let xBig = BI.makeWrappedInt64(xval64)
|
|
@@ -998,41 +966,33 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
998
966
|
reducedInteger(result)
|
|
999
967
|
}
|
|
1000
968
|
},
|
|
1001
|
-
t when
|
|
969
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1002
970
|
// Promote x to bigint and do operation
|
|
1003
971
|
let xBig = BI.makeWrappedInt64(xval)
|
|
1004
972
|
let result = if (isSub) BI.sub(xBig, y) else BI.add(xBig, y)
|
|
1005
973
|
Memory.decRef(xBig)
|
|
1006
974
|
reducedBigInteger(result)
|
|
1007
975
|
},
|
|
1008
|
-
t when
|
|
976
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1009
977
|
let xBig = BI.makeWrappedInt64(xval)
|
|
1010
978
|
let yNumerator = boxedRationalNumerator(y)
|
|
1011
979
|
let yDenominator = boxedRationalDenominator(y)
|
|
1012
980
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
1013
981
|
Memory.decRef(xBig)
|
|
1014
|
-
let result =
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
982
|
+
let result = if (isSub)
|
|
983
|
+
BI.sub(expandedXNumerator, yNumerator)
|
|
984
|
+
else
|
|
985
|
+
BI.add(expandedXNumerator, yNumerator)
|
|
986
|
+
let ret = reducedFractionBigInt(result, yDenominator, false)
|
|
1018
987
|
Memory.decRef(expandedXNumerator)
|
|
1019
988
|
Memory.decRef(result)
|
|
1020
989
|
ret
|
|
1021
990
|
},
|
|
1022
|
-
t when
|
|
1023
|
-
|
|
1024
|
-
let yBoxedVal = boxedFloat32Number(y)
|
|
1025
|
-
let result =
|
|
1026
|
-
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
1027
|
-
else WasmF32.add(xval, yBoxedVal)
|
|
1028
|
-
newFloat32(result)
|
|
1029
|
-
},
|
|
1030
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
991
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
992
|
+
use WasmF64.{ (+), (-) }
|
|
1031
993
|
let xval = WasmF64.convertI64S(xval)
|
|
1032
994
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1033
|
-
let result =
|
|
1034
|
-
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1035
|
-
else WasmF64.add(xval, yBoxedVal)
|
|
995
|
+
let result = if (isSub) xval - yBoxedVal else xval + yBoxedVal
|
|
1036
996
|
newFloat64(result)
|
|
1037
997
|
},
|
|
1038
998
|
_ => {
|
|
@@ -1042,40 +1002,16 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
1042
1002
|
}
|
|
1043
1003
|
}
|
|
1044
1004
|
|
|
1045
|
-
@unsafe
|
|
1046
|
-
let numberAddSubFloat32Help = (xval, y, isSub) => {
|
|
1047
|
-
if (
|
|
1048
|
-
!isSimpleNumber(y) &&
|
|
1049
|
-
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
1050
|
-
) {
|
|
1051
|
-
// Special case: promote to f64 if RHS is f64
|
|
1052
|
-
let xval = WasmF64.promoteF32(xval)
|
|
1053
|
-
let yval = boxedFloat64Number(y)
|
|
1054
|
-
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
1055
|
-
newFloat64(result)
|
|
1056
|
-
} else {
|
|
1057
|
-
// incRef y to reuse it via WasmI32.toGrain
|
|
1058
|
-
Memory.incRef(y)
|
|
1059
|
-
let yval = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
1060
|
-
let result = if (isSub) WasmF32.sub(xval, yval) else WasmF32.add(xval, yval)
|
|
1061
|
-
newFloat32(result)
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
1005
|
@unsafe
|
|
1066
1006
|
let numberAddSubFloat64Help = (xval, y, isSub) => {
|
|
1007
|
+
use WasmF64.{ (+), (-) }
|
|
1067
1008
|
// incRef y to reuse it via WasmI32.toGrain
|
|
1068
1009
|
Memory.incRef(y)
|
|
1069
1010
|
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
1070
|
-
let result = if (isSub)
|
|
1011
|
+
let result = if (isSub) xval - yval else xval + yval
|
|
1071
1012
|
newFloat64(result)
|
|
1072
1013
|
}
|
|
1073
1014
|
|
|
1074
|
-
@unsafe
|
|
1075
|
-
let numberAddSubInt32Help = (xval, y, isSub) => {
|
|
1076
|
-
numberAddSubInt64Help(WasmI64.extendI32S(xval), y, isSub)
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
1015
|
@unsafe
|
|
1080
1016
|
let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
1081
1017
|
if (isSimpleNumber(y)) {
|
|
@@ -1091,18 +1027,7 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1091
1027
|
} else {
|
|
1092
1028
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1093
1029
|
match (yBoxedNumberTag) {
|
|
1094
|
-
t when
|
|
1095
|
-
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1096
|
-
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1097
|
-
let res = if (isSub) {
|
|
1098
|
-
BI.sub(x, yBig)
|
|
1099
|
-
} else {
|
|
1100
|
-
BI.add(x, yBig)
|
|
1101
|
-
}
|
|
1102
|
-
Memory.decRef(yBig)
|
|
1103
|
-
reducedBigInteger(res)
|
|
1104
|
-
},
|
|
1105
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1030
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1106
1031
|
let yBoxedVal = boxedInt64Number(y)
|
|
1107
1032
|
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1108
1033
|
let res = if (isSub) {
|
|
@@ -1113,7 +1038,7 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1113
1038
|
Memory.decRef(yBig)
|
|
1114
1039
|
reducedBigInteger(res)
|
|
1115
1040
|
},
|
|
1116
|
-
t when
|
|
1041
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1117
1042
|
let res = if (isSub) {
|
|
1118
1043
|
BI.sub(x, y)
|
|
1119
1044
|
} else {
|
|
@@ -1121,32 +1046,24 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1121
1046
|
}
|
|
1122
1047
|
reducedBigInteger(res)
|
|
1123
1048
|
},
|
|
1124
|
-
t when
|
|
1049
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1125
1050
|
let yNumerator = boxedRationalNumerator(y)
|
|
1126
1051
|
let yDenominator = boxedRationalDenominator(y)
|
|
1127
1052
|
let expandedXNumerator = BI.mul(x, yDenominator)
|
|
1128
|
-
let result =
|
|
1129
|
-
|
|
1130
|
-
|
|
1053
|
+
let result = if (isSub)
|
|
1054
|
+
BI.sub(expandedXNumerator, yNumerator)
|
|
1055
|
+
else
|
|
1056
|
+
BI.add(expandedXNumerator, yNumerator)
|
|
1131
1057
|
Memory.decRef(expandedXNumerator)
|
|
1132
|
-
let ret = reducedFractionBigInt(result, yDenominator)
|
|
1058
|
+
let ret = reducedFractionBigInt(result, yDenominator, false)
|
|
1133
1059
|
Memory.decRef(result)
|
|
1134
1060
|
ret
|
|
1135
1061
|
},
|
|
1136
|
-
t when
|
|
1137
|
-
|
|
1138
|
-
let yBoxedVal = boxedFloat32Number(y)
|
|
1139
|
-
let result =
|
|
1140
|
-
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
1141
|
-
else WasmF32.add(xval, yBoxedVal)
|
|
1142
|
-
newFloat32(result)
|
|
1143
|
-
},
|
|
1144
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1062
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1063
|
+
use WasmF64.{ (+), (-) }
|
|
1145
1064
|
let xval = BI.toFloat64(x)
|
|
1146
1065
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1147
|
-
let result =
|
|
1148
|
-
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1149
|
-
else WasmF64.add(xval, yBoxedVal)
|
|
1066
|
+
let result = if (isSub) xval - yBoxedVal else xval + yBoxedVal
|
|
1150
1067
|
newFloat64(result)
|
|
1151
1068
|
},
|
|
1152
1069
|
_ => {
|
|
@@ -1156,6 +1073,120 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1156
1073
|
}
|
|
1157
1074
|
}
|
|
1158
1075
|
|
|
1076
|
+
@unsafe
|
|
1077
|
+
provide let addSubRational = (x, y, isSub, keepRational) => {
|
|
1078
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1079
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1080
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1081
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1082
|
+
if (BI.eq(xDenominator, yDenominator)) {
|
|
1083
|
+
let newNumerator = if (isSub)
|
|
1084
|
+
BI.sub(xNumerator, yNumerator)
|
|
1085
|
+
else
|
|
1086
|
+
BI.add(xNumerator, yNumerator)
|
|
1087
|
+
let ret = reducedFractionBigInt(newNumerator, xDenominator, keepRational)
|
|
1088
|
+
Memory.decRef(newNumerator)
|
|
1089
|
+
ret
|
|
1090
|
+
} else {
|
|
1091
|
+
let numerator1 = BI.mul(xNumerator, yDenominator)
|
|
1092
|
+
let numerator2 = BI.mul(yNumerator, xDenominator)
|
|
1093
|
+
let numerator = if (isSub)
|
|
1094
|
+
BI.sub(numerator1, numerator2)
|
|
1095
|
+
else
|
|
1096
|
+
BI.add(numerator1, numerator2)
|
|
1097
|
+
let denominator = BI.mul(xDenominator, yDenominator)
|
|
1098
|
+
let ret = reducedFractionBigInt(numerator, denominator, keepRational)
|
|
1099
|
+
Memory.decRef(numerator1)
|
|
1100
|
+
Memory.decRef(numerator2)
|
|
1101
|
+
Memory.decRef(numerator)
|
|
1102
|
+
ret
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
@unsafe
|
|
1107
|
+
provide let timesDivideRational = (x, y, isDivide, keepRational) => {
|
|
1108
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1109
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1110
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1111
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1112
|
+
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
1113
|
+
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
1114
|
+
let numerator = if (isDivide)
|
|
1115
|
+
BI.mul(xNumerator, yDenominator)
|
|
1116
|
+
else
|
|
1117
|
+
BI.mul(xNumerator, yNumerator)
|
|
1118
|
+
let denominator = if (isDivide)
|
|
1119
|
+
BI.mul(xDenominator, yNumerator)
|
|
1120
|
+
else
|
|
1121
|
+
BI.mul(xDenominator, yDenominator)
|
|
1122
|
+
reducedFractionBigInt(numerator, denominator, keepRational)
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
@unsafe
|
|
1126
|
+
provide let rationalsEqual = (x, y) => {
|
|
1127
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1128
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1129
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1130
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1131
|
+
BI.eq(xNumerator, yNumerator) && BI.eq(xDenominator, yDenominator)
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
@unsafe
|
|
1135
|
+
provide let cmpRationals = (x, y) => {
|
|
1136
|
+
// Comparing rationals efficiently is an open problem
|
|
1137
|
+
// Producing a definitive answer is quite expensive, so if the two
|
|
1138
|
+
// values are not strictly equal we approximate an answer
|
|
1139
|
+
|
|
1140
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1141
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1142
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1143
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1144
|
+
|
|
1145
|
+
if (
|
|
1146
|
+
BI.cmp(xNumerator, yNumerator) == 0n &&
|
|
1147
|
+
BI.cmp(xDenominator, yDenominator) == 0n
|
|
1148
|
+
) {
|
|
1149
|
+
0n
|
|
1150
|
+
} else {
|
|
1151
|
+
use WasmF64.{ (/), (<) }
|
|
1152
|
+
let xf = BI.toFloat64(xNumerator) / BI.toFloat64(xDenominator)
|
|
1153
|
+
let yf = BI.toFloat64(yNumerator) / BI.toFloat64(yDenominator)
|
|
1154
|
+
if (xf < yf) -1n else 1n
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Finds the numerator of the rational number.
|
|
1160
|
+
*
|
|
1161
|
+
* @param x: The rational number to inspect
|
|
1162
|
+
* @returns The numerator of the rational number
|
|
1163
|
+
*
|
|
1164
|
+
* @since v0.6.0
|
|
1165
|
+
*/
|
|
1166
|
+
@unsafe
|
|
1167
|
+
provide let rationalNumerator = (x: Rational) => {
|
|
1168
|
+
let x = WasmI32.fromGrain(x)
|
|
1169
|
+
let num = boxedRationalNumerator(x)
|
|
1170
|
+
Memory.incRef(num)
|
|
1171
|
+
WasmI32.toGrain(reducedBigInteger(num)): Number
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Finds the denominator of the rational number.
|
|
1176
|
+
*
|
|
1177
|
+
* @param x: The rational number to inspect
|
|
1178
|
+
* @returns The denominator of the rational number
|
|
1179
|
+
*
|
|
1180
|
+
* @since v0.6.0
|
|
1181
|
+
*/
|
|
1182
|
+
@unsafe
|
|
1183
|
+
provide let rationalDenominator = (x: Rational) => {
|
|
1184
|
+
let x = WasmI32.fromGrain(x)
|
|
1185
|
+
let num = boxedRationalDenominator(x)
|
|
1186
|
+
Memory.incRef(num)
|
|
1187
|
+
WasmI32.toGrain(reducedBigInteger(num)): Number
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1159
1190
|
@unsafe
|
|
1160
1191
|
let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
1161
1192
|
let xNumerator = boxedRationalNumerator(x)
|
|
@@ -1164,95 +1195,53 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1164
1195
|
let yval = untagSimple(y)
|
|
1165
1196
|
let yBig = BI.makeWrappedInt32(yval)
|
|
1166
1197
|
let expandedYNumerator = BI.mul(xDenominator, yBig)
|
|
1167
|
-
let result =
|
|
1168
|
-
|
|
1169
|
-
|
|
1198
|
+
let result = if (isSub)
|
|
1199
|
+
BI.sub(xNumerator, expandedYNumerator)
|
|
1200
|
+
else
|
|
1201
|
+
BI.add(xNumerator, expandedYNumerator)
|
|
1170
1202
|
Memory.decRef(expandedYNumerator)
|
|
1171
1203
|
Memory.decRef(yBig)
|
|
1172
|
-
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1204
|
+
let ret = reducedFractionBigInt(result, xDenominator, false)
|
|
1173
1205
|
Memory.decRef(result)
|
|
1174
1206
|
ret
|
|
1175
1207
|
} else {
|
|
1176
1208
|
let ytag = boxedNumberTag(y)
|
|
1177
1209
|
match (ytag) {
|
|
1178
|
-
t when
|
|
1210
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1179
1211
|
// The one case we don't delegate is rational +/- rational
|
|
1180
|
-
|
|
1181
|
-
let xDenominator = boxedRationalDenominator(x)
|
|
1182
|
-
let yNumerator = boxedRationalNumerator(y)
|
|
1183
|
-
let yDenominator = boxedRationalDenominator(y)
|
|
1184
|
-
if (BI.eq(xDenominator, yDenominator)) {
|
|
1185
|
-
let newNumerator =
|
|
1186
|
-
if (isSub) BI.sub(xNumerator, yNumerator)
|
|
1187
|
-
else BI.add(xNumerator, yNumerator)
|
|
1188
|
-
let ret = reducedFractionBigInt(newNumerator, xDenominator)
|
|
1189
|
-
Memory.decRef(newNumerator)
|
|
1190
|
-
ret
|
|
1191
|
-
} else {
|
|
1192
|
-
let numerator1 = BI.mul(xNumerator, yDenominator)
|
|
1193
|
-
let numerator2 = BI.mul(yNumerator, xDenominator)
|
|
1194
|
-
let numerator =
|
|
1195
|
-
if (isSub) BI.sub(numerator1, numerator2)
|
|
1196
|
-
else BI.add(numerator1, numerator2)
|
|
1197
|
-
let denominator = BI.mul(xDenominator, yDenominator)
|
|
1198
|
-
let ret = reducedFractionBigInt(numerator, denominator)
|
|
1199
|
-
Memory.decRef(numerator1)
|
|
1200
|
-
Memory.decRef(numerator2)
|
|
1201
|
-
Memory.decRef(numerator)
|
|
1202
|
-
ret
|
|
1203
|
-
}
|
|
1204
|
-
},
|
|
1205
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1206
|
-
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1207
|
-
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1208
|
-
Memory.decRef(yBig)
|
|
1209
|
-
let result =
|
|
1210
|
-
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1211
|
-
else BI.add(xNumerator, expandedYNumerator)
|
|
1212
|
-
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1213
|
-
Memory.decRef(expandedYNumerator)
|
|
1214
|
-
Memory.decRef(result)
|
|
1215
|
-
ret
|
|
1212
|
+
addSubRational(x, y, isSub, false)
|
|
1216
1213
|
},
|
|
1217
|
-
t when
|
|
1214
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1218
1215
|
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1219
1216
|
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1220
1217
|
Memory.decRef(yBig)
|
|
1221
|
-
let result =
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1218
|
+
let result = if (isSub)
|
|
1219
|
+
BI.sub(xNumerator, expandedYNumerator)
|
|
1220
|
+
else
|
|
1221
|
+
BI.add(xNumerator, expandedYNumerator)
|
|
1222
|
+
let ret = reducedFractionBigInt(result, xDenominator, false)
|
|
1225
1223
|
Memory.decRef(expandedYNumerator)
|
|
1226
1224
|
Memory.decRef(result)
|
|
1227
1225
|
ret
|
|
1228
1226
|
},
|
|
1229
|
-
t when
|
|
1227
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1230
1228
|
let expandedYNumerator = BI.mul(xDenominator, y)
|
|
1231
|
-
let result =
|
|
1232
|
-
|
|
1233
|
-
|
|
1229
|
+
let result = if (isSub)
|
|
1230
|
+
BI.sub(xNumerator, expandedYNumerator)
|
|
1231
|
+
else
|
|
1232
|
+
BI.add(xNumerator, expandedYNumerator)
|
|
1234
1233
|
Memory.decRef(expandedYNumerator)
|
|
1235
|
-
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1234
|
+
let ret = reducedFractionBigInt(result, xDenominator, false)
|
|
1236
1235
|
Memory.decRef(result)
|
|
1237
1236
|
ret
|
|
1238
1237
|
},
|
|
1239
|
-
t when
|
|
1240
|
-
|
|
1241
|
-
BI.toFloat32(xNumerator),
|
|
1242
|
-
BI.toFloat32(xDenominator)
|
|
1243
|
-
)
|
|
1244
|
-
let result =
|
|
1245
|
-
if (isSub) WasmF32.sub(xval, boxedFloat32Number(y))
|
|
1246
|
-
else WasmF32.add(xval, boxedFloat32Number(y))
|
|
1247
|
-
newFloat32(result)
|
|
1248
|
-
},
|
|
1249
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1238
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1239
|
+
use WasmF64.{ (/), (+), (-) }
|
|
1250
1240
|
let xnumfloat = BI.toFloat64(xNumerator)
|
|
1251
1241
|
let xdenfloat = BI.toFloat64(xDenominator)
|
|
1252
|
-
let xval =
|
|
1242
|
+
let xval = xnumfloat / xdenfloat
|
|
1253
1243
|
let yval = boxedFloat64Number(y)
|
|
1254
|
-
let result =
|
|
1255
|
-
if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
1244
|
+
let result = if (isSub) xval - yval else xval + yval
|
|
1256
1245
|
let ret = newFloat64(result)
|
|
1257
1246
|
ret
|
|
1258
1247
|
},
|
|
@@ -1270,22 +1259,16 @@ let numberAddSubHelp = (x, y, isSub) => {
|
|
|
1270
1259
|
} else {
|
|
1271
1260
|
let xtag = boxedNumberTag(x)
|
|
1272
1261
|
match (xtag) {
|
|
1273
|
-
t when
|
|
1274
|
-
numberAddSubInt32Help(boxedInt32Number(x), y, isSub)
|
|
1275
|
-
},
|
|
1276
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1262
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1277
1263
|
numberAddSubInt64Help(boxedInt64Number(x), y, isSub)
|
|
1278
1264
|
},
|
|
1279
|
-
t when
|
|
1265
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1280
1266
|
numberAddSubBigIntHelp(x, y, isSub)
|
|
1281
1267
|
},
|
|
1282
|
-
t when
|
|
1268
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1283
1269
|
numberAddSubRationalHelp(x, y, isSub)
|
|
1284
1270
|
},
|
|
1285
|
-
t when
|
|
1286
|
-
numberAddSubFloat32Help(boxedFloat32Number(x), y, isSub)
|
|
1287
|
-
},
|
|
1288
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1271
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1289
1272
|
numberAddSubFloat64Help(boxedFloat64Number(x), y, isSub)
|
|
1290
1273
|
},
|
|
1291
1274
|
_ => {
|
|
@@ -1312,9 +1295,10 @@ let numberSub = (x, y) => {
|
|
|
1312
1295
|
|
|
1313
1296
|
@unsafe
|
|
1314
1297
|
let safeI64Multiply = (x, y) => {
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1298
|
+
use WasmI64.{ (!=), (*), (/) }
|
|
1299
|
+
let prod = x * y
|
|
1300
|
+
if (x != 0N) {
|
|
1301
|
+
if (prod / x != y) {
|
|
1318
1302
|
let xBig = BI.makeWrappedInt64(x)
|
|
1319
1303
|
let yBig = BI.makeWrappedInt64(y)
|
|
1320
1304
|
let result = BI.mul(xBig, yBig)
|
|
@@ -1340,15 +1324,7 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
1340
1324
|
} else {
|
|
1341
1325
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1342
1326
|
match (yBoxedNumberTag) {
|
|
1343
|
-
t when
|
|
1344
|
-
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1345
|
-
if (isDivide) {
|
|
1346
|
-
reducedFraction64(xval, yBoxedVal)
|
|
1347
|
-
} else {
|
|
1348
|
-
safeI64Multiply(xval, yBoxedVal)
|
|
1349
|
-
}
|
|
1350
|
-
},
|
|
1351
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1327
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1352
1328
|
let yBoxedVal = boxedInt64Number(y)
|
|
1353
1329
|
if (isDivide) {
|
|
1354
1330
|
reducedFraction64(xval, yBoxedVal)
|
|
@@ -1356,52 +1332,44 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
1356
1332
|
safeI64Multiply(xval, yBoxedVal)
|
|
1357
1333
|
}
|
|
1358
1334
|
},
|
|
1359
|
-
t when
|
|
1335
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1360
1336
|
let xBig = BI.makeWrappedInt64(xval)
|
|
1361
1337
|
let ret = if (isDivide) {
|
|
1362
|
-
reducedFractionBigInt(xBig, y)
|
|
1338
|
+
reducedFractionBigInt(xBig, y, false)
|
|
1363
1339
|
} else {
|
|
1364
1340
|
reducedBigInteger(BI.mul(xBig, y))
|
|
1365
1341
|
}
|
|
1366
1342
|
Memory.decRef(xBig)
|
|
1367
1343
|
ret
|
|
1368
1344
|
},
|
|
1369
|
-
t when
|
|
1345
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1370
1346
|
let yNumerator = boxedRationalNumerator(y)
|
|
1371
1347
|
let yDenominator = boxedRationalDenominator(y)
|
|
1372
1348
|
let xBig = BI.makeWrappedInt64(xval)
|
|
1373
1349
|
let ret = if (isDivide) {
|
|
1374
1350
|
// x / (a / b) == (x * b) / a
|
|
1375
1351
|
let numerator = BI.mul(xBig, yDenominator)
|
|
1376
|
-
let ret = reducedFractionBigInt(numerator, yNumerator)
|
|
1352
|
+
let ret = reducedFractionBigInt(numerator, yNumerator, false)
|
|
1377
1353
|
Memory.decRef(numerator)
|
|
1378
1354
|
ret
|
|
1379
1355
|
} else {
|
|
1380
1356
|
// x * (a / b) == (x * a) / b
|
|
1381
1357
|
let numerator = BI.mul(xBig, yNumerator)
|
|
1382
|
-
let ret = reducedFractionBigInt(numerator, yDenominator)
|
|
1358
|
+
let ret = reducedFractionBigInt(numerator, yDenominator, false)
|
|
1383
1359
|
Memory.decRef(numerator)
|
|
1384
1360
|
ret
|
|
1385
1361
|
}
|
|
1386
1362
|
Memory.decRef(xBig)
|
|
1387
1363
|
ret
|
|
1388
1364
|
},
|
|
1389
|
-
t when
|
|
1390
|
-
|
|
1391
|
-
let yBoxedVal = boxedFloat32Number(y)
|
|
1392
|
-
if (isDivide) {
|
|
1393
|
-
newFloat32(WasmF32.div(xval, yBoxedVal))
|
|
1394
|
-
} else {
|
|
1395
|
-
newFloat32(WasmF32.mul(xval, yBoxedVal))
|
|
1396
|
-
}
|
|
1397
|
-
},
|
|
1398
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1365
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1366
|
+
use WasmF64.{ (/), (*) }
|
|
1399
1367
|
let xval = WasmF64.convertI64S(xval)
|
|
1400
1368
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1401
1369
|
if (isDivide) {
|
|
1402
|
-
newFloat64(
|
|
1370
|
+
newFloat64(xval / yBoxedVal)
|
|
1403
1371
|
} else {
|
|
1404
|
-
newFloat64(
|
|
1372
|
+
newFloat64(xval * yBoxedVal)
|
|
1405
1373
|
}
|
|
1406
1374
|
},
|
|
1407
1375
|
_ => {
|
|
@@ -1416,7 +1384,7 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
|
1416
1384
|
if (isSimpleNumber(y)) {
|
|
1417
1385
|
let yBig = BI.makeWrappedInt32(untagSimple(y))
|
|
1418
1386
|
let ret = if (isDivide) {
|
|
1419
|
-
reducedFractionBigInt(x, yBig)
|
|
1387
|
+
reducedFractionBigInt(x, yBig, false)
|
|
1420
1388
|
} else {
|
|
1421
1389
|
reducedBigInteger(BI.mul(x, yBig))
|
|
1422
1390
|
}
|
|
@@ -1425,70 +1393,49 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
|
1425
1393
|
} else {
|
|
1426
1394
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1427
1395
|
match (yBoxedNumberTag) {
|
|
1428
|
-
t when
|
|
1429
|
-
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1430
|
-
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1431
|
-
let ret = if (isDivide) {
|
|
1432
|
-
reducedFractionBigInt(x, yBig)
|
|
1433
|
-
} else {
|
|
1434
|
-
reducedBigInteger(BI.mul(x, yBig))
|
|
1435
|
-
}
|
|
1436
|
-
Memory.decRef(yBig)
|
|
1437
|
-
ret
|
|
1438
|
-
},
|
|
1439
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1396
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1440
1397
|
let yBoxedVal = boxedInt64Number(y)
|
|
1441
1398
|
let yBig = BI.makeWrappedInt64(yBoxedVal)
|
|
1442
1399
|
let ret = if (isDivide) {
|
|
1443
|
-
reducedFractionBigInt(x, yBig)
|
|
1400
|
+
reducedFractionBigInt(x, yBig, false)
|
|
1444
1401
|
} else {
|
|
1445
1402
|
reducedBigInteger(BI.mul(x, yBig))
|
|
1446
1403
|
}
|
|
1447
1404
|
Memory.decRef(yBig)
|
|
1448
1405
|
ret
|
|
1449
1406
|
},
|
|
1450
|
-
t when
|
|
1407
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1451
1408
|
if (isDivide) {
|
|
1452
|
-
reducedFractionBigInt(x, y)
|
|
1409
|
+
reducedFractionBigInt(x, y, false)
|
|
1453
1410
|
} else {
|
|
1454
1411
|
reducedBigInteger(BI.mul(x, y))
|
|
1455
1412
|
}
|
|
1456
1413
|
},
|
|
1457
|
-
t when
|
|
1414
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1458
1415
|
let yNumerator = boxedRationalNumerator(y)
|
|
1459
1416
|
let yDenominator = boxedRationalDenominator(y)
|
|
1460
1417
|
if (isDivide) {
|
|
1461
1418
|
// x / (a / b) == (x * b) / a
|
|
1462
1419
|
let numerator = BI.mul(x, yDenominator)
|
|
1463
|
-
let ret = reducedFractionBigInt(numerator, yNumerator)
|
|
1420
|
+
let ret = reducedFractionBigInt(numerator, yNumerator, false)
|
|
1464
1421
|
Memory.decRef(numerator)
|
|
1465
1422
|
ret
|
|
1466
1423
|
} else {
|
|
1467
1424
|
// x * (a / b) == (x * a) / b
|
|
1468
1425
|
let numerator = BI.mul(x, yNumerator)
|
|
1469
|
-
let ret = reducedFractionBigInt(numerator, yDenominator)
|
|
1426
|
+
let ret = reducedFractionBigInt(numerator, yDenominator, false)
|
|
1470
1427
|
Memory.decRef(numerator)
|
|
1471
1428
|
ret
|
|
1472
1429
|
}
|
|
1473
1430
|
},
|
|
1474
|
-
t when
|
|
1475
|
-
|
|
1476
|
-
// we can only fit rather small bigints (<4 limbs) into an F32
|
|
1477
|
-
let xval = BI.toFloat64(x)
|
|
1478
|
-
let yBoxedVal = WasmF64.promoteF32(boxedFloat32Number(y))
|
|
1479
|
-
if (isDivide) {
|
|
1480
|
-
newFloat64(WasmF64.div(xval, yBoxedVal))
|
|
1481
|
-
} else {
|
|
1482
|
-
newFloat64(WasmF64.mul(xval, yBoxedVal))
|
|
1483
|
-
}
|
|
1484
|
-
},
|
|
1485
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1431
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1432
|
+
use WasmF64.{ (/), (*) }
|
|
1486
1433
|
let xval = BI.toFloat64(x)
|
|
1487
1434
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1488
1435
|
if (isDivide) {
|
|
1489
|
-
newFloat64(
|
|
1436
|
+
newFloat64(xval / yBoxedVal)
|
|
1490
1437
|
} else {
|
|
1491
|
-
newFloat64(
|
|
1438
|
+
newFloat64(xval * yBoxedVal)
|
|
1492
1439
|
}
|
|
1493
1440
|
},
|
|
1494
1441
|
_ => {
|
|
@@ -1505,13 +1452,9 @@ let numberTimesDivideSimpleHelp = (x, y, isDivide) => {
|
|
|
1505
1452
|
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
1506
1453
|
}
|
|
1507
1454
|
|
|
1508
|
-
@unsafe
|
|
1509
|
-
let numberTimesDivideInt32Help = (xval, y, isDivide) => {
|
|
1510
|
-
numberTimesDivideInt64Help(WasmI64.extendI32S(xval), y, isDivide)
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
1455
|
@unsafe
|
|
1514
1456
|
let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
1457
|
+
use WasmI32.{ (!=) }
|
|
1515
1458
|
// Division isn't commutative, so we actually need to do the work
|
|
1516
1459
|
let xNumerator = boxedRationalNumerator(x)
|
|
1517
1460
|
let xDenominator = boxedRationalDenominator(x)
|
|
@@ -1520,17 +1463,17 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1520
1463
|
let ret = if (isDivide) {
|
|
1521
1464
|
// (a / b) / y == a / (b * y)
|
|
1522
1465
|
let denominator = BI.mul(xDenominator, yBig)
|
|
1523
|
-
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1466
|
+
let ret = reducedFractionBigInt(xNumerator, denominator, false)
|
|
1524
1467
|
Memory.decRef(denominator)
|
|
1525
1468
|
ret
|
|
1526
1469
|
} else {
|
|
1527
1470
|
// (a / b) * y == (a * y) / b
|
|
1528
1471
|
let numerator = BI.mul(xNumerator, yBig)
|
|
1529
|
-
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1472
|
+
let ret = reducedFractionBigInt(numerator, xDenominator, false)
|
|
1530
1473
|
Memory.decRef(numerator)
|
|
1531
1474
|
ret
|
|
1532
1475
|
}
|
|
1533
|
-
if (
|
|
1476
|
+
if (yBig != ret) {
|
|
1534
1477
|
Memory.decRef(yBig)
|
|
1535
1478
|
void
|
|
1536
1479
|
}
|
|
@@ -1538,95 +1481,51 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1538
1481
|
} else {
|
|
1539
1482
|
let ytag = boxedNumberTag(y)
|
|
1540
1483
|
match (ytag) {
|
|
1541
|
-
t when
|
|
1542
|
-
// Same idea as above
|
|
1543
|
-
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1544
|
-
let ret = if (isDivide) {
|
|
1545
|
-
// (a / b) / y == a / (b * y)
|
|
1546
|
-
let denominator = BI.mul(xDenominator, yBig)
|
|
1547
|
-
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1548
|
-
Memory.decRef(denominator)
|
|
1549
|
-
ret
|
|
1550
|
-
} else {
|
|
1551
|
-
// (a / b) * y == (a * y) / b
|
|
1552
|
-
let numerator = BI.mul(xNumerator, yBig)
|
|
1553
|
-
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1554
|
-
Memory.decRef(numerator)
|
|
1555
|
-
ret
|
|
1556
|
-
}
|
|
1557
|
-
Memory.decRef(yBig)
|
|
1558
|
-
ret
|
|
1559
|
-
},
|
|
1560
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1484
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1561
1485
|
// Same idea as above
|
|
1562
1486
|
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1563
1487
|
let ret = if (isDivide) {
|
|
1564
1488
|
// (a / b) / y == a / (b * y)
|
|
1565
1489
|
let denominator = BI.mul(xDenominator, yBig)
|
|
1566
|
-
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1490
|
+
let ret = reducedFractionBigInt(xNumerator, denominator, false)
|
|
1567
1491
|
Memory.decRef(denominator)
|
|
1568
1492
|
ret
|
|
1569
1493
|
} else {
|
|
1570
1494
|
// (a / b) * y == (a * y) / b
|
|
1571
1495
|
let numerator = BI.mul(xNumerator, yBig)
|
|
1572
|
-
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1496
|
+
let ret = reducedFractionBigInt(numerator, xDenominator, false)
|
|
1573
1497
|
Memory.decRef(numerator)
|
|
1574
1498
|
ret
|
|
1575
1499
|
}
|
|
1576
1500
|
Memory.decRef(yBig)
|
|
1577
1501
|
ret
|
|
1578
1502
|
},
|
|
1579
|
-
t when
|
|
1503
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1580
1504
|
if (isDivide) {
|
|
1581
1505
|
// (a / b) / y == a / (b * y)
|
|
1582
1506
|
let denominator = BI.mul(xDenominator, y)
|
|
1583
|
-
let ret = reducedFractionBigInt(xNumerator, denominator)
|
|
1507
|
+
let ret = reducedFractionBigInt(xNumerator, denominator, false)
|
|
1584
1508
|
Memory.decRef(denominator)
|
|
1585
1509
|
ret
|
|
1586
1510
|
} else {
|
|
1587
1511
|
// (a / b) * y == (a * y) / b
|
|
1588
1512
|
let numerator = BI.mul(xNumerator, y)
|
|
1589
|
-
let ret = reducedFractionBigInt(numerator, xDenominator)
|
|
1513
|
+
let ret = reducedFractionBigInt(numerator, xDenominator, false)
|
|
1590
1514
|
Memory.decRef(numerator)
|
|
1591
1515
|
ret
|
|
1592
1516
|
}
|
|
1593
1517
|
},
|
|
1594
|
-
t when
|
|
1595
|
-
|
|
1596
|
-
let xDenominator = boxedRationalDenominator(x)
|
|
1597
|
-
let yNumerator = boxedRationalNumerator(y)
|
|
1598
|
-
let yDenominator = boxedRationalDenominator(y)
|
|
1599
|
-
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
1600
|
-
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
1601
|
-
let numerator =
|
|
1602
|
-
if (isDivide) BI.mul(xNumerator, yDenominator)
|
|
1603
|
-
else BI.mul(xNumerator, yNumerator)
|
|
1604
|
-
let denominator =
|
|
1605
|
-
if (isDivide) BI.mul(xDenominator, yNumerator)
|
|
1606
|
-
else BI.mul(xDenominator, yDenominator)
|
|
1607
|
-
reducedFractionBigInt(numerator, denominator)
|
|
1608
|
-
},
|
|
1609
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1610
|
-
// TODO(#1190): We should probably use something more accurate if possible here
|
|
1611
|
-
let asFloat = WasmF32.demoteF64(
|
|
1612
|
-
WasmF64.div(BI.toFloat64(xNumerator), BI.toFloat64(xDenominator))
|
|
1613
|
-
)
|
|
1614
|
-
if (isDivide) {
|
|
1615
|
-
newFloat32(WasmF32.div(asFloat, boxedFloat32Number(y)))
|
|
1616
|
-
} else {
|
|
1617
|
-
newFloat32(WasmF32.mul(asFloat, boxedFloat32Number(y)))
|
|
1618
|
-
}
|
|
1518
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1519
|
+
timesDivideRational(x, y, isDivide, false)
|
|
1619
1520
|
},
|
|
1620
|
-
t when
|
|
1521
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1522
|
+
use WasmF64.{ (/), (*) }
|
|
1621
1523
|
// TODO(#1190): We should probably use something more accurate if possible here
|
|
1622
|
-
let asFloat =
|
|
1623
|
-
BI.toFloat64(xNumerator),
|
|
1624
|
-
BI.toFloat64(xDenominator)
|
|
1625
|
-
)
|
|
1524
|
+
let asFloat = BI.toFloat64(xNumerator) / BI.toFloat64(xDenominator)
|
|
1626
1525
|
if (isDivide) {
|
|
1627
|
-
newFloat64(
|
|
1526
|
+
newFloat64(asFloat / boxedFloat64Number(y))
|
|
1628
1527
|
} else {
|
|
1629
|
-
newFloat64(
|
|
1528
|
+
newFloat64(asFloat * boxedFloat64Number(y))
|
|
1630
1529
|
}
|
|
1631
1530
|
},
|
|
1632
1531
|
_ => {
|
|
@@ -1638,63 +1537,34 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1638
1537
|
|
|
1639
1538
|
@unsafe
|
|
1640
1539
|
let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
1540
|
+
use WasmF64.{ (/), (*) }
|
|
1641
1541
|
// incRef y to reuse it via WasmI32.toGrain
|
|
1642
1542
|
Memory.incRef(y)
|
|
1643
1543
|
let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
1644
1544
|
if (isDivide) {
|
|
1645
|
-
newFloat64(
|
|
1545
|
+
newFloat64(x / yAsFloat)
|
|
1646
1546
|
} else {
|
|
1647
|
-
newFloat64(
|
|
1547
|
+
newFloat64(x * yAsFloat)
|
|
1648
1548
|
}
|
|
1649
1549
|
}
|
|
1650
1550
|
|
|
1651
1551
|
@unsafe
|
|
1652
|
-
let
|
|
1653
|
-
if (
|
|
1654
|
-
|
|
1655
|
-
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1656
|
-
) {
|
|
1657
|
-
// Special case: f32->f64 promotion
|
|
1658
|
-
if (isDivide) {
|
|
1659
|
-
newFloat64(WasmF64.div(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
1660
|
-
} else {
|
|
1661
|
-
newFloat64(WasmF64.mul(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
1662
|
-
}
|
|
1663
|
-
} else {
|
|
1664
|
-
// incRef y to reuse it via WasmI32.toGrain
|
|
1665
|
-
Memory.incRef(y)
|
|
1666
|
-
let yAsFloat = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
1667
|
-
if (isDivide) {
|
|
1668
|
-
newFloat32(WasmF32.div(x, yAsFloat))
|
|
1669
|
-
} else {
|
|
1670
|
-
newFloat32(WasmF32.mul(x, yAsFloat))
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
@unsafe
|
|
1676
|
-
let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
1677
|
-
if (isSimpleNumber(x)) {
|
|
1678
|
-
numberTimesDivideSimpleHelp(x, y, isDivide)
|
|
1552
|
+
let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
1553
|
+
if (isSimpleNumber(x)) {
|
|
1554
|
+
numberTimesDivideSimpleHelp(x, y, isDivide)
|
|
1679
1555
|
} else {
|
|
1680
1556
|
let xtag = boxedNumberTag(x)
|
|
1681
1557
|
match (xtag) {
|
|
1682
|
-
t when
|
|
1683
|
-
numberTimesDivideInt32Help(boxedInt32Number(x), y, isDivide)
|
|
1684
|
-
},
|
|
1685
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1558
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1686
1559
|
numberTimesDivideInt64Help(boxedInt64Number(x), y, isDivide)
|
|
1687
1560
|
},
|
|
1688
|
-
t when
|
|
1561
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1689
1562
|
numberTimesDivideBigIntHelp(x, y, isDivide)
|
|
1690
1563
|
},
|
|
1691
|
-
t when
|
|
1564
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1692
1565
|
numberTimesDivideRationalHelp(x, y, isDivide)
|
|
1693
1566
|
},
|
|
1694
|
-
t when
|
|
1695
|
-
numberTimesDivideFloat32Help(boxedFloat32Number(x), y, isDivide)
|
|
1696
|
-
},
|
|
1697
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1567
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1698
1568
|
numberTimesDivideFloat64Help(boxedFloat64Number(x), y, isDivide)
|
|
1699
1569
|
},
|
|
1700
1570
|
_ => {
|
|
@@ -1720,33 +1590,47 @@ let numberDivide = (x, y) => {
|
|
|
1720
1590
|
*/
|
|
1721
1591
|
|
|
1722
1592
|
@unsafe
|
|
1723
|
-
let i64abs = x =>
|
|
1593
|
+
let i64abs = x => {
|
|
1594
|
+
use WasmI64.{ (-), (>=) }
|
|
1595
|
+
if (x >= 0N) x else 0N - x
|
|
1596
|
+
}
|
|
1724
1597
|
|
|
1725
1598
|
@unsafe
|
|
1726
1599
|
let numberMod = (x, y) => {
|
|
1600
|
+
use WasmI64.{ (!=), (-), (*), (<), (>) }
|
|
1727
1601
|
// incRef x and y to reuse them via WasmI32.toGrain
|
|
1728
1602
|
Memory.incRef(x)
|
|
1729
1603
|
Memory.incRef(y)
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
if (WasmI64.ne(modval, 0N))
|
|
1743
|
-
WasmI64.mul(
|
|
1744
|
-
WasmI64.sub(i64abs(yval), modval),
|
|
1745
|
-
if (WasmI64.ltS(yval, 0N)) -1N else 1N
|
|
1746
|
-
) else modval
|
|
1747
|
-
reducedInteger(result)
|
|
1604
|
+
if (isFloat(x) || isFloat(y) || isRational(x) || isRational(y)) {
|
|
1605
|
+
use WasmF64.{ (==), (/), (*), (-) }
|
|
1606
|
+
let xval = coerceNumberToWasmF64(WasmI32.toGrain(x): Number)
|
|
1607
|
+
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
1608
|
+
let yInfinite = yval == InfinityW || yval == -InfinityW
|
|
1609
|
+
if (yval == 0.0W || yInfinite && (xval == InfinityW || xval == -InfinityW)) {
|
|
1610
|
+
newFloat64(NaNW)
|
|
1611
|
+
} else if (yInfinite) {
|
|
1612
|
+
newFloat64(xval)
|
|
1613
|
+
} else {
|
|
1614
|
+
newFloat64(xval - WasmF64.trunc(xval / yval) * yval)
|
|
1615
|
+
}
|
|
1748
1616
|
} else {
|
|
1749
|
-
|
|
1617
|
+
let xval = coerceNumberToWasmI64(WasmI32.toGrain(x): Number)
|
|
1618
|
+
let yval = coerceNumberToWasmI64(WasmI32.toGrain(y): Number)
|
|
1619
|
+
if (WasmI64.eqz(yval)) {
|
|
1620
|
+
throw Exception.ModuloByZero
|
|
1621
|
+
}
|
|
1622
|
+
// We implement true modulo
|
|
1623
|
+
if (xval < 0N && yval > 0N || xval > 0N && yval < 0N) {
|
|
1624
|
+
let modval = WasmI64.remS(i64abs(xval), i64abs(yval))
|
|
1625
|
+
let result = if (modval != 0N) {
|
|
1626
|
+
i64abs(yval) - modval * (if (yval < 0N) -1N else 1N)
|
|
1627
|
+
} else {
|
|
1628
|
+
modval
|
|
1629
|
+
}
|
|
1630
|
+
reducedInteger(result)
|
|
1631
|
+
} else {
|
|
1632
|
+
reducedInteger(WasmI64.remS(xval, yval))
|
|
1633
|
+
}
|
|
1750
1634
|
}
|
|
1751
1635
|
}
|
|
1752
1636
|
|
|
@@ -1772,25 +1656,19 @@ let cmpBigInt = (x: WasmI32, y: WasmI32) => {
|
|
|
1772
1656
|
} else {
|
|
1773
1657
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1774
1658
|
match (yBoxedNumberTag) {
|
|
1775
|
-
t when
|
|
1776
|
-
BI.cmpI64(x, WasmI64.extendI32S(boxedInt32Number(y)))
|
|
1777
|
-
},
|
|
1778
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1659
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1779
1660
|
BI.cmpI64(x, boxedInt64Number(y))
|
|
1780
1661
|
},
|
|
1781
|
-
t when
|
|
1662
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1782
1663
|
BI.cmp(x, y)
|
|
1783
1664
|
},
|
|
1784
|
-
t when
|
|
1665
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1785
1666
|
let tmp = BI.mul(x, boxedRationalDenominator(y))
|
|
1786
1667
|
let ret = BI.cmp(tmp, boxedRationalNumerator(y))
|
|
1787
1668
|
Memory.decRef(tmp)
|
|
1788
1669
|
ret
|
|
1789
1670
|
},
|
|
1790
|
-
t when
|
|
1791
|
-
BI.cmpF32(x, boxedFloat32Number(y))
|
|
1792
|
-
},
|
|
1793
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1671
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1794
1672
|
BI.cmpF64(x, boxedFloat64Number(y))
|
|
1795
1673
|
},
|
|
1796
1674
|
_ => {
|
|
@@ -1804,55 +1682,51 @@ let cmpBigInt = (x: WasmI32, y: WasmI32) => {
|
|
|
1804
1682
|
// unlike regular float logic, NaN is considered equal to itself and
|
|
1805
1683
|
// smaller than any other number
|
|
1806
1684
|
@unsafe
|
|
1807
|
-
let cmpFloat = (x: WasmI32, y: WasmI32
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
WasmF64.promoteF32(boxedFloat32Number(x))
|
|
1812
|
-
}
|
|
1685
|
+
let cmpFloat = (x: WasmI32, y: WasmI32) => {
|
|
1686
|
+
use WasmF64.{ (!=), (<), (>), (/) }
|
|
1687
|
+
use WasmI32.{ (-) }
|
|
1688
|
+
let xf = boxedFloat64Number(x)
|
|
1813
1689
|
if (isSimpleNumber(y)) {
|
|
1814
1690
|
let yf = WasmF64.convertI32S(untagSimple(y))
|
|
1815
1691
|
// special NaN cases
|
|
1816
|
-
if (
|
|
1817
|
-
if (
|
|
1692
|
+
if (xf != xf) {
|
|
1693
|
+
if (yf != yf) {
|
|
1818
1694
|
0n
|
|
1819
1695
|
} else {
|
|
1820
1696
|
-1n
|
|
1821
1697
|
}
|
|
1822
|
-
} else if (
|
|
1823
|
-
if (
|
|
1698
|
+
} else if (yf != yf) {
|
|
1699
|
+
if (xf != xf) {
|
|
1824
1700
|
0n
|
|
1825
1701
|
} else {
|
|
1826
1702
|
1n
|
|
1827
1703
|
}
|
|
1828
1704
|
} else {
|
|
1829
|
-
if (
|
|
1705
|
+
if (xf < yf) {
|
|
1706
|
+
-1n
|
|
1707
|
+
} else if (xf > yf) {
|
|
1708
|
+
1n
|
|
1709
|
+
} else {
|
|
1710
|
+
0n
|
|
1711
|
+
}
|
|
1830
1712
|
}
|
|
1831
1713
|
} else {
|
|
1832
1714
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1833
1715
|
if (yBoxedNumberTag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG) {
|
|
1834
|
-
|
|
1716
|
+
0n - cmpBigInt(y, x)
|
|
1835
1717
|
} else {
|
|
1836
1718
|
let yf = match (yBoxedNumberTag) {
|
|
1837
|
-
t when
|
|
1838
|
-
WasmF64.convertI32S(boxedInt32Number(y))
|
|
1839
|
-
},
|
|
1840
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1719
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1841
1720
|
WasmF64.convertI64S(boxedInt64Number(y))
|
|
1842
1721
|
},
|
|
1843
|
-
t when
|
|
1722
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1844
1723
|
throw InvariantViolation
|
|
1845
1724
|
},
|
|
1846
|
-
t when
|
|
1847
|
-
|
|
1848
|
-
BI.toFloat64(boxedRationalNumerator(y)),
|
|
1725
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1726
|
+
BI.toFloat64(boxedRationalNumerator(y)) /
|
|
1849
1727
|
BI.toFloat64(boxedRationalDenominator(y))
|
|
1850
|
-
)
|
|
1851
|
-
},
|
|
1852
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1853
|
-
WasmF64.promoteF32(boxedFloat32Number(y))
|
|
1854
1728
|
},
|
|
1855
|
-
t when
|
|
1729
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1856
1730
|
boxedFloat64Number(y)
|
|
1857
1731
|
},
|
|
1858
1732
|
_ => {
|
|
@@ -1860,66 +1734,75 @@ let cmpFloat = (x: WasmI32, y: WasmI32, is64: Bool) => {
|
|
|
1860
1734
|
},
|
|
1861
1735
|
}
|
|
1862
1736
|
// special NaN cases
|
|
1863
|
-
if (
|
|
1864
|
-
if (
|
|
1737
|
+
if (xf != xf) {
|
|
1738
|
+
if (yf != yf) {
|
|
1865
1739
|
0n
|
|
1866
1740
|
} else {
|
|
1867
1741
|
-1n
|
|
1868
1742
|
}
|
|
1869
|
-
} else if (
|
|
1870
|
-
if (
|
|
1743
|
+
} else if (yf != yf) {
|
|
1744
|
+
if (xf != xf) {
|
|
1871
1745
|
0n
|
|
1872
1746
|
} else {
|
|
1873
1747
|
1n
|
|
1874
1748
|
}
|
|
1875
1749
|
} else {
|
|
1876
|
-
if (
|
|
1750
|
+
if (xf < yf) {
|
|
1751
|
+
-1n
|
|
1752
|
+
} else if (xf > yf) {
|
|
1753
|
+
1n
|
|
1754
|
+
} else {
|
|
1755
|
+
0n
|
|
1756
|
+
}
|
|
1877
1757
|
}
|
|
1878
1758
|
}
|
|
1879
1759
|
}
|
|
1880
1760
|
}
|
|
1881
1761
|
|
|
1882
1762
|
@unsafe
|
|
1883
|
-
let cmpSmallInt = (x: WasmI32, y: WasmI32
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
WasmI64.extendI32S(boxedInt32Number(x))
|
|
1888
|
-
}
|
|
1763
|
+
let cmpSmallInt = (x: WasmI32, y: WasmI32) => {
|
|
1764
|
+
use WasmI64.{ (<), (>) }
|
|
1765
|
+
use WasmI32.{ (-) }
|
|
1766
|
+
let xi = boxedInt64Number(x)
|
|
1889
1767
|
if (isSimpleNumber(y)) {
|
|
1890
1768
|
let yi = WasmI64.extendI32S(untagSimple(y))
|
|
1891
|
-
if (
|
|
1769
|
+
if (xi < yi) {
|
|
1770
|
+
-1n
|
|
1771
|
+
} else if (xi > yi) {
|
|
1772
|
+
1n
|
|
1773
|
+
} else {
|
|
1774
|
+
0n
|
|
1775
|
+
}
|
|
1892
1776
|
} else {
|
|
1893
1777
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1894
1778
|
match (yBoxedNumberTag) {
|
|
1895
|
-
t when
|
|
1896
|
-
let yi = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1897
|
-
if (WasmI64.ltS(xi, yi)) -1n else if (WasmI64.gtS(xi, yi)) 1n else 0n
|
|
1898
|
-
},
|
|
1899
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1779
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1900
1780
|
let yi = boxedInt64Number(y)
|
|
1901
|
-
if (
|
|
1781
|
+
if (xi < yi) {
|
|
1782
|
+
-1n
|
|
1783
|
+
} else if (xi > yi) {
|
|
1784
|
+
1n
|
|
1785
|
+
} else {
|
|
1786
|
+
0n
|
|
1787
|
+
}
|
|
1902
1788
|
},
|
|
1903
|
-
t when
|
|
1904
|
-
|
|
1789
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1790
|
+
0n - cmpBigInt(y, x)
|
|
1905
1791
|
},
|
|
1906
|
-
t when
|
|
1792
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1793
|
+
use WasmF64.{ (<), (/) }
|
|
1907
1794
|
// Rationals and ints are never considered equal
|
|
1908
1795
|
if (
|
|
1909
|
-
WasmF64.
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
) -1n else 1n
|
|
1917
|
-
},
|
|
1918
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1919
|
-
WasmI32.sub(0n, cmpFloat(y, x, false))
|
|
1796
|
+
WasmF64.convertI64S(xi) <
|
|
1797
|
+
BI.toFloat64(boxedRationalNumerator(y)) /
|
|
1798
|
+
BI.toFloat64(boxedRationalDenominator(y))
|
|
1799
|
+
)
|
|
1800
|
+
-1n
|
|
1801
|
+
else
|
|
1802
|
+
1n
|
|
1920
1803
|
},
|
|
1921
|
-
t when
|
|
1922
|
-
|
|
1804
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1805
|
+
0n - cmpFloat(y, x)
|
|
1923
1806
|
},
|
|
1924
1807
|
_ => {
|
|
1925
1808
|
throw UnknownNumberTag
|
|
@@ -1930,57 +1813,27 @@ let cmpSmallInt = (x: WasmI32, y: WasmI32, is64: Bool) => {
|
|
|
1930
1813
|
|
|
1931
1814
|
@unsafe
|
|
1932
1815
|
let cmpRational = (x: WasmI32, y: WasmI32) => {
|
|
1816
|
+
use WasmI32.{ (-) }
|
|
1933
1817
|
if (isSimpleNumber(y)) {
|
|
1934
|
-
|
|
1935
|
-
|
|
1818
|
+
use WasmF64.{ (/), (<) }
|
|
1819
|
+
let xf = BI.toFloat64(boxedRationalNumerator(x)) /
|
|
1936
1820
|
BI.toFloat64(boxedRationalDenominator(x))
|
|
1937
|
-
)
|
|
1938
1821
|
// Rationals and ints are never considered equal
|
|
1939
|
-
if (
|
|
1822
|
+
if (xf < WasmF64.convertI32S(untagSimple(y))) -1n else 1n
|
|
1940
1823
|
} else {
|
|
1941
1824
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1942
1825
|
match (yBoxedNumberTag) {
|
|
1943
|
-
t when
|
|
1944
|
-
|
|
1826
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1827
|
+
0n - cmpSmallInt(y, x)
|
|
1945
1828
|
},
|
|
1946
|
-
t when
|
|
1947
|
-
|
|
1829
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1830
|
+
0n - cmpBigInt(y, x)
|
|
1948
1831
|
},
|
|
1949
|
-
t when
|
|
1950
|
-
|
|
1951
|
-
},
|
|
1952
|
-
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1953
|
-
// Comparing rationals efficiently is an open problem
|
|
1954
|
-
// Producing a definitive answer is quite expensive, so if the two
|
|
1955
|
-
// values are not strictly equal we approximate an answer
|
|
1956
|
-
|
|
1957
|
-
let xNumerator = boxedRationalNumerator(x)
|
|
1958
|
-
let xDenominator = boxedRationalDenominator(x)
|
|
1959
|
-
let yNumerator = boxedRationalNumerator(y)
|
|
1960
|
-
let yDenominator = boxedRationalDenominator(y)
|
|
1961
|
-
|
|
1962
|
-
if (
|
|
1963
|
-
BI.cmp(xNumerator, yNumerator) == 0n &&
|
|
1964
|
-
BI.cmp(xDenominator, yDenominator) == 0n
|
|
1965
|
-
) {
|
|
1966
|
-
0n
|
|
1967
|
-
} else {
|
|
1968
|
-
let xf = WasmF64.div(
|
|
1969
|
-
BI.toFloat64(xNumerator),
|
|
1970
|
-
BI.toFloat64(xDenominator)
|
|
1971
|
-
)
|
|
1972
|
-
let yf = WasmF64.div(
|
|
1973
|
-
BI.toFloat64(yNumerator),
|
|
1974
|
-
BI.toFloat64(yDenominator)
|
|
1975
|
-
)
|
|
1976
|
-
if (WasmF64.lt(xf, yf)) -1n else 1n
|
|
1977
|
-
}
|
|
1832
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1833
|
+
cmpRationals(x, y)
|
|
1978
1834
|
},
|
|
1979
|
-
t when
|
|
1980
|
-
|
|
1981
|
-
},
|
|
1982
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1983
|
-
WasmI32.sub(0n, cmpFloat(y, x, true))
|
|
1835
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1836
|
+
0n - cmpFloat(y, x)
|
|
1984
1837
|
},
|
|
1985
1838
|
_ => {
|
|
1986
1839
|
throw UnknownNumberTag
|
|
@@ -1990,31 +1843,26 @@ let cmpRational = (x: WasmI32, y: WasmI32) => {
|
|
|
1990
1843
|
}
|
|
1991
1844
|
|
|
1992
1845
|
@unsafe
|
|
1993
|
-
|
|
1846
|
+
provide let cmp = (x: WasmI32, y: WasmI32) => {
|
|
1847
|
+
use WasmI32.{ (-) }
|
|
1994
1848
|
if (isSimpleNumber(x)) {
|
|
1995
1849
|
if (isSimpleNumber(y)) {
|
|
1996
1850
|
// fast comparison path for simple numbers
|
|
1997
|
-
|
|
1851
|
+
x - y
|
|
1998
1852
|
} else {
|
|
1999
1853
|
let yBoxedNumberTag = boxedNumberTag(y)
|
|
2000
1854
|
match (yBoxedNumberTag) {
|
|
2001
|
-
t when
|
|
2002
|
-
|
|
2003
|
-
},
|
|
2004
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
2005
|
-
WasmI32.sub(0n, cmpSmallInt(y, x, true))
|
|
1855
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1856
|
+
0n - cmpSmallInt(y, x)
|
|
2006
1857
|
},
|
|
2007
|
-
t when
|
|
2008
|
-
|
|
1858
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
1859
|
+
0n - cmpBigInt(y, x)
|
|
2009
1860
|
},
|
|
2010
|
-
t when
|
|
2011
|
-
|
|
1861
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
1862
|
+
0n - cmpRational(y, x)
|
|
2012
1863
|
},
|
|
2013
|
-
t when
|
|
2014
|
-
|
|
2015
|
-
},
|
|
2016
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
2017
|
-
WasmI32.sub(0n, cmpFloat(y, x, true))
|
|
1864
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1865
|
+
0n - cmpFloat(y, x)
|
|
2018
1866
|
},
|
|
2019
1867
|
_ => {
|
|
2020
1868
|
throw UnknownNumberTag
|
|
@@ -2024,23 +1872,17 @@ export let cmp = (x: WasmI32, y: WasmI32) => {
|
|
|
2024
1872
|
} else {
|
|
2025
1873
|
let xBoxedNumberTag = boxedNumberTag(x)
|
|
2026
1874
|
match (xBoxedNumberTag) {
|
|
2027
|
-
t when
|
|
2028
|
-
cmpSmallInt(x, y
|
|
2029
|
-
},
|
|
2030
|
-
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
2031
|
-
cmpSmallInt(x, y, true)
|
|
1875
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
1876
|
+
cmpSmallInt(x, y)
|
|
2032
1877
|
},
|
|
2033
|
-
t when
|
|
1878
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
2034
1879
|
cmpBigInt(x, y)
|
|
2035
1880
|
},
|
|
2036
|
-
t when
|
|
1881
|
+
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
2037
1882
|
cmpRational(x, y)
|
|
2038
1883
|
},
|
|
2039
|
-
t when
|
|
2040
|
-
cmpFloat(x, y
|
|
2041
|
-
},
|
|
2042
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
2043
|
-
cmpFloat(x, y, true)
|
|
1884
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
1885
|
+
cmpFloat(x, y)
|
|
2044
1886
|
},
|
|
2045
1887
|
_ => {
|
|
2046
1888
|
throw UnknownNumberTag
|
|
@@ -2056,36 +1898,76 @@ export let cmp = (x: WasmI32, y: WasmI32) => {
|
|
|
2056
1898
|
// NaN being considered equal to itself and less than all other numbers in
|
|
2057
1899
|
// this case).
|
|
2058
1900
|
|
|
1901
|
+
/**
|
|
1902
|
+
* Checks if the first operand is less than the second operand.
|
|
1903
|
+
*
|
|
1904
|
+
* @param num1: The first operand
|
|
1905
|
+
* @param num2: The second operand
|
|
1906
|
+
* @returns `true` if the first operand is less than the second operand or `false` otherwise
|
|
1907
|
+
*
|
|
1908
|
+
* @since v0.1.0
|
|
1909
|
+
*/
|
|
2059
1910
|
@unsafe
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
let
|
|
2063
|
-
|
|
1911
|
+
provide let (<) = (num1: Number, num2: Number) => {
|
|
1912
|
+
use WasmI32.{ (<) }
|
|
1913
|
+
let x = WasmI32.fromGrain(num1)
|
|
1914
|
+
let y = WasmI32.fromGrain(num2)
|
|
1915
|
+
!isNaN(x) && !isNaN(y) && cmp(x, y) < 0n
|
|
2064
1916
|
}
|
|
2065
1917
|
|
|
1918
|
+
/**
|
|
1919
|
+
* Checks if the first operand is greater than the second operand.
|
|
1920
|
+
*
|
|
1921
|
+
* @param num1: The first operand
|
|
1922
|
+
* @param num2: The second operand
|
|
1923
|
+
* @returns `true` if the first operand is greater than the second operand or `false` otherwise
|
|
1924
|
+
*
|
|
1925
|
+
* @since v0.1.0
|
|
1926
|
+
*/
|
|
2066
1927
|
@unsafe
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
let
|
|
2070
|
-
|
|
1928
|
+
provide let (>) = (num1: Number, num2: Number) => {
|
|
1929
|
+
use WasmI32.{ (>) }
|
|
1930
|
+
let x = WasmI32.fromGrain(num1)
|
|
1931
|
+
let y = WasmI32.fromGrain(num2)
|
|
1932
|
+
!isNaN(x) && !isNaN(y) && cmp(x, y) > 0n
|
|
2071
1933
|
}
|
|
2072
1934
|
|
|
1935
|
+
/**
|
|
1936
|
+
* Checks if the first operand is less than or equal to the second operand.
|
|
1937
|
+
*
|
|
1938
|
+
* @param num1: The first operand
|
|
1939
|
+
* @param num2: The second operand
|
|
1940
|
+
* @returns `true` if the first operand is less than or equal to the second operand or `false` otherwise
|
|
1941
|
+
*
|
|
1942
|
+
* @since v0.1.0
|
|
1943
|
+
*/
|
|
2073
1944
|
@unsafe
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
let
|
|
2077
|
-
|
|
1945
|
+
provide let (<=) = (num1: Number, num2: Number) => {
|
|
1946
|
+
use WasmI32.{ (<=) }
|
|
1947
|
+
let x = WasmI32.fromGrain(num1)
|
|
1948
|
+
let y = WasmI32.fromGrain(num2)
|
|
1949
|
+
!isNaN(x) && !isNaN(y) && cmp(x, y) <= 0n
|
|
2078
1950
|
}
|
|
2079
1951
|
|
|
1952
|
+
/**
|
|
1953
|
+
* Checks if the first operand is greater than or equal to the second operand.
|
|
1954
|
+
*
|
|
1955
|
+
* @param num1: The first operand
|
|
1956
|
+
* @param num2: The second operand
|
|
1957
|
+
* @returns `true` if the first operand is greater than or equal to the second operand or `false` otherwise
|
|
1958
|
+
*
|
|
1959
|
+
* @since v0.1.0
|
|
1960
|
+
*/
|
|
2080
1961
|
@unsafe
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
let
|
|
2084
|
-
|
|
1962
|
+
provide let (>=) = (num1: Number, num2: Number) => {
|
|
1963
|
+
use WasmI32.{ (>=) }
|
|
1964
|
+
let x = WasmI32.fromGrain(num1)
|
|
1965
|
+
let y = WasmI32.fromGrain(num2)
|
|
1966
|
+
!isNaN(x) && !isNaN(y) && cmp(x, y) >= 0n
|
|
2085
1967
|
}
|
|
2086
1968
|
|
|
2087
1969
|
@unsafe
|
|
2088
|
-
|
|
1970
|
+
provide let compare = (x: Number, y: Number) => {
|
|
2089
1971
|
let x = WasmI32.fromGrain(x)
|
|
2090
1972
|
let y = WasmI32.fromGrain(y)
|
|
2091
1973
|
WasmI32.toGrain(tagSimple(cmp(x, y))): Number
|
|
@@ -2096,7 +1978,7 @@ export let compare = (x: Number, y: Number) => {
|
|
|
2096
1978
|
*/
|
|
2097
1979
|
|
|
2098
1980
|
@unsafe
|
|
2099
|
-
|
|
1981
|
+
provide let numberEq = (x: Number, y: Number) => {
|
|
2100
1982
|
let x = WasmI32.fromGrain(x)
|
|
2101
1983
|
let y = WasmI32.fromGrain(y)
|
|
2102
1984
|
numberEqual(x, y)
|
|
@@ -2108,143 +1990,221 @@ export let numberEq = (x: Number, y: Number) => {
|
|
|
2108
1990
|
*/
|
|
2109
1991
|
// TODO(#306): Semantics around when things should stay i32/i64
|
|
2110
1992
|
|
|
1993
|
+
/**
|
|
1994
|
+
* Computes the bitwise NOT of the operand.
|
|
1995
|
+
*
|
|
1996
|
+
* @param value: The operand
|
|
1997
|
+
* @returns Containing the inverted bits of the operand
|
|
1998
|
+
*
|
|
1999
|
+
* @since v0.2.0
|
|
2000
|
+
*/
|
|
2111
2001
|
@unsafe
|
|
2112
|
-
|
|
2113
|
-
let xw32 = WasmI32.fromGrain(
|
|
2002
|
+
provide let lnot = (value: Number) => {
|
|
2003
|
+
let xw32 = WasmI32.fromGrain(value)
|
|
2114
2004
|
if (isBigInt(xw32)) {
|
|
2115
2005
|
WasmI32.toGrain(reducedBigInteger(BI.bitwiseNot(xw32))): Number
|
|
2116
2006
|
} else {
|
|
2117
|
-
let xval = coerceNumberToWasmI64(
|
|
2007
|
+
let xval = coerceNumberToWasmI64(value)
|
|
2118
2008
|
WasmI32.toGrain(reducedInteger(i64not(xval))): Number
|
|
2119
2009
|
}
|
|
2120
2010
|
}
|
|
2121
2011
|
|
|
2012
|
+
/**
|
|
2013
|
+
* Shifts the bits of the value left by the given number of bits.
|
|
2014
|
+
*
|
|
2015
|
+
* @param value: The value to shift
|
|
2016
|
+
* @param amount: The number of bits to shift by
|
|
2017
|
+
* @returns The shifted value
|
|
2018
|
+
*
|
|
2019
|
+
* @since v0.3.0
|
|
2020
|
+
* @history v0.2.0: Originally named `lsl`
|
|
2021
|
+
* @history v0.3.0: Renamed to `<<`
|
|
2022
|
+
*/
|
|
2122
2023
|
@unsafe
|
|
2123
|
-
|
|
2124
|
-
|
|
2024
|
+
provide let (<<) = (value: Number, amount: Number) => {
|
|
2025
|
+
use WasmI64.{ (-), (<<) }
|
|
2026
|
+
let xw32 = WasmI32.fromGrain(value)
|
|
2125
2027
|
if (isBigInt(xw32)) {
|
|
2126
|
-
let yval = coerceNumberToWasmI32(
|
|
2028
|
+
let yval = coerceNumberToWasmI32(amount)
|
|
2127
2029
|
WasmI32.toGrain(reducedBigInteger(BI.shl(xw32, yval))): Number
|
|
2128
2030
|
} else {
|
|
2129
|
-
let xval = coerceNumberToWasmI64(
|
|
2130
|
-
let yval = coerceNumberToWasmI64(
|
|
2031
|
+
let xval = coerceNumberToWasmI64(value)
|
|
2032
|
+
let yval = coerceNumberToWasmI64(amount)
|
|
2131
2033
|
// if the number will be shifted beyond the end of the i64 range, promote to BigInt
|
|
2132
2034
|
// (note that we subtract one leading zero, since the leading bit is the sign bit)
|
|
2133
|
-
if (WasmI64.leU(WasmI64.
|
|
2134
|
-
let xbi = coerceNumberToBigInt(
|
|
2135
|
-
let yval = coerceNumberToWasmI32(
|
|
2035
|
+
if (WasmI64.leU(WasmI64.clz(i64abs(xval)) - 1N, yval)) {
|
|
2036
|
+
let xbi = coerceNumberToBigInt(value)
|
|
2037
|
+
let yval = coerceNumberToWasmI32(amount)
|
|
2136
2038
|
WasmI32.toGrain(reducedBigInteger(BI.shl(xbi, yval))): Number
|
|
2137
2039
|
} else {
|
|
2138
|
-
WasmI32.toGrain(reducedInteger(
|
|
2040
|
+
WasmI32.toGrain(reducedInteger(xval << yval)): Number
|
|
2139
2041
|
}
|
|
2140
2042
|
}
|
|
2141
2043
|
}
|
|
2142
2044
|
|
|
2045
|
+
/**
|
|
2046
|
+
* Shifts the bits of the value right by the given number of bits, preserving the sign bit.
|
|
2047
|
+
*
|
|
2048
|
+
* @param value: The value to shift
|
|
2049
|
+
* @param amount: The amount to shift by
|
|
2050
|
+
* @returns The shifted value
|
|
2051
|
+
*
|
|
2052
|
+
* @since v0.3.0
|
|
2053
|
+
* @history v0.2.0: Originally named `lsr`
|
|
2054
|
+
* @history v0.3.0: Renamed to `>>>`
|
|
2055
|
+
*/
|
|
2143
2056
|
@unsafe
|
|
2144
|
-
|
|
2145
|
-
|
|
2057
|
+
provide let (>>>) = (value: Number, amount: Number) => {
|
|
2058
|
+
use WasmI64.{ (>>>) }
|
|
2059
|
+
let xw32 = WasmI32.fromGrain(value)
|
|
2146
2060
|
if (isBigInt(xw32)) {
|
|
2147
|
-
let yval = coerceNumberToWasmI32(
|
|
2061
|
+
let yval = coerceNumberToWasmI32(amount)
|
|
2148
2062
|
// [NOTE]: For BigInts, shrU is the same as shrS because there
|
|
2149
2063
|
// are an *infinite* number of leading ones
|
|
2150
2064
|
WasmI32.toGrain(reducedBigInteger(BI.shrS(xw32, yval))): Number
|
|
2151
2065
|
} else {
|
|
2152
|
-
let xval = coerceNumberToWasmI64(
|
|
2153
|
-
let yval = coerceNumberToWasmI64(
|
|
2154
|
-
WasmI32.toGrain(reducedInteger(
|
|
2066
|
+
let xval = coerceNumberToWasmI64(value)
|
|
2067
|
+
let yval = coerceNumberToWasmI64(amount)
|
|
2068
|
+
WasmI32.toGrain(reducedInteger(xval >>> yval)): Number
|
|
2155
2069
|
}
|
|
2156
2070
|
}
|
|
2157
2071
|
|
|
2072
|
+
/**
|
|
2073
|
+
* Computes the bitwise AND (`&`) on the given operands.
|
|
2074
|
+
*
|
|
2075
|
+
* @param value1: The first operand
|
|
2076
|
+
* @param value2: The second operand
|
|
2077
|
+
* @returns Containing a `1` in each bit position for which the corresponding bits of both operands are `1`
|
|
2078
|
+
*
|
|
2079
|
+
* @since v0.3.0
|
|
2080
|
+
* @history v0.2.0: Originally named `land`
|
|
2081
|
+
* @history v0.3.0: Renamed to `&`
|
|
2082
|
+
*/
|
|
2158
2083
|
@unsafe
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
let
|
|
2084
|
+
provide let (&) = (value1: Number, value2: Number) => {
|
|
2085
|
+
use WasmI64.{ (&) }
|
|
2086
|
+
let xw32 = WasmI32.fromGrain(value1)
|
|
2087
|
+
let yw32 = WasmI32.fromGrain(value2)
|
|
2162
2088
|
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
2163
|
-
let xval = coerceNumberToBigInt(
|
|
2164
|
-
let yval = coerceNumberToBigInt(
|
|
2165
|
-
let ret = WasmI32.toGrain(
|
|
2166
|
-
|
|
2167
|
-
)
|
|
2168
|
-
if (!WasmI32.eq(xw32, xval)) {
|
|
2089
|
+
let xval = coerceNumberToBigInt(value1)
|
|
2090
|
+
let yval = coerceNumberToBigInt(value2)
|
|
2091
|
+
let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseAnd(xval, yval))):
|
|
2092
|
+
Number
|
|
2093
|
+
if (!(xw32 == xval)) {
|
|
2169
2094
|
Memory.decRef(xval)
|
|
2170
2095
|
void
|
|
2171
2096
|
}
|
|
2172
|
-
if (!
|
|
2097
|
+
if (!(yw32 == yval)) {
|
|
2173
2098
|
Memory.decRef(yval)
|
|
2174
2099
|
void
|
|
2175
2100
|
}
|
|
2176
2101
|
ret
|
|
2177
2102
|
} else {
|
|
2178
|
-
let xval = coerceNumberToWasmI64(
|
|
2179
|
-
let yval = coerceNumberToWasmI64(
|
|
2180
|
-
WasmI32.toGrain(reducedInteger(
|
|
2103
|
+
let xval = coerceNumberToWasmI64(value1)
|
|
2104
|
+
let yval = coerceNumberToWasmI64(value2)
|
|
2105
|
+
WasmI32.toGrain(reducedInteger(xval & yval)): Number
|
|
2181
2106
|
}
|
|
2182
2107
|
}
|
|
2183
2108
|
|
|
2109
|
+
/**
|
|
2110
|
+
* Computes the bitwise OR (`|`) on the given operands.
|
|
2111
|
+
*
|
|
2112
|
+
* @param value1: The first operand
|
|
2113
|
+
* @param value2: The second operand
|
|
2114
|
+
* @returns Containing a `1` in each bit position for which the corresponding bits of either or both operands are `1`
|
|
2115
|
+
*
|
|
2116
|
+
* @since v0.3.0
|
|
2117
|
+
* @history v0.2.0: Originally named `lor`
|
|
2118
|
+
* @history v0.3.0: Renamed to `|`
|
|
2119
|
+
*/
|
|
2184
2120
|
@unsafe
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
let
|
|
2121
|
+
provide let (|) = (value1: Number, value2: Number) => {
|
|
2122
|
+
use WasmI64.{ (|) }
|
|
2123
|
+
let xw32 = WasmI32.fromGrain(value1)
|
|
2124
|
+
let yw32 = WasmI32.fromGrain(value2)
|
|
2188
2125
|
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
2189
|
-
let xval = coerceNumberToBigInt(
|
|
2190
|
-
let yval = coerceNumberToBigInt(
|
|
2191
|
-
let ret = WasmI32.toGrain(
|
|
2192
|
-
|
|
2193
|
-
)
|
|
2194
|
-
if (!WasmI32.eq(xw32, xval)) {
|
|
2126
|
+
let xval = coerceNumberToBigInt(value1)
|
|
2127
|
+
let yval = coerceNumberToBigInt(value2)
|
|
2128
|
+
let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseOr(xval, yval))):
|
|
2129
|
+
Number
|
|
2130
|
+
if (!(xw32 == xval)) {
|
|
2195
2131
|
Memory.decRef(xval)
|
|
2196
2132
|
void
|
|
2197
2133
|
}
|
|
2198
|
-
if (!
|
|
2134
|
+
if (!(yw32 == yval)) {
|
|
2199
2135
|
Memory.decRef(yval)
|
|
2200
2136
|
void
|
|
2201
2137
|
}
|
|
2202
2138
|
ret
|
|
2203
2139
|
} else {
|
|
2204
|
-
let xval = coerceNumberToWasmI64(
|
|
2205
|
-
let yval = coerceNumberToWasmI64(
|
|
2206
|
-
WasmI32.toGrain(reducedInteger(
|
|
2140
|
+
let xval = coerceNumberToWasmI64(value1)
|
|
2141
|
+
let yval = coerceNumberToWasmI64(value2)
|
|
2142
|
+
WasmI32.toGrain(reducedInteger(xval | yval)): Number
|
|
2207
2143
|
}
|
|
2208
2144
|
}
|
|
2209
2145
|
|
|
2146
|
+
/**
|
|
2147
|
+
* Computes the bitwise XOR (`^`) on the given operands.
|
|
2148
|
+
*
|
|
2149
|
+
* @param value1: The first operand
|
|
2150
|
+
* @param value2: The second operand
|
|
2151
|
+
* @returns Containing a `1` in each bit position for which the corresponding bits of either but not both operands are `1`
|
|
2152
|
+
*
|
|
2153
|
+
* @since v0.3.0
|
|
2154
|
+
* @history v0.1.0: The `^` operator was originally an alias of `unbox`
|
|
2155
|
+
* @history v0.2.0: Originally named `lxor`
|
|
2156
|
+
* @history v0.3.0: Renamed to `^`
|
|
2157
|
+
*/
|
|
2210
2158
|
@unsafe
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
let
|
|
2159
|
+
provide let (^) = (value1: Number, value2: Number) => {
|
|
2160
|
+
use WasmI64.{ (^) }
|
|
2161
|
+
let xw32 = WasmI32.fromGrain(value1)
|
|
2162
|
+
let yw32 = WasmI32.fromGrain(value2)
|
|
2214
2163
|
if (isBigInt(xw32) || isBigInt(yw32)) {
|
|
2215
|
-
let xval = coerceNumberToBigInt(
|
|
2216
|
-
let yval = coerceNumberToBigInt(
|
|
2217
|
-
let ret = WasmI32.toGrain(
|
|
2218
|
-
|
|
2219
|
-
)
|
|
2220
|
-
if (!WasmI32.eq(xw32, xval)) {
|
|
2164
|
+
let xval = coerceNumberToBigInt(value1)
|
|
2165
|
+
let yval = coerceNumberToBigInt(value2)
|
|
2166
|
+
let ret = WasmI32.toGrain(reducedBigInteger(BI.bitwiseXor(xval, yval))):
|
|
2167
|
+
Number
|
|
2168
|
+
if (!(xw32 == xval)) {
|
|
2221
2169
|
Memory.decRef(xval)
|
|
2222
2170
|
void
|
|
2223
2171
|
}
|
|
2224
|
-
if (!
|
|
2172
|
+
if (!(yw32 == yval)) {
|
|
2225
2173
|
Memory.decRef(yval)
|
|
2226
2174
|
void
|
|
2227
2175
|
}
|
|
2228
2176
|
ret
|
|
2229
2177
|
} else {
|
|
2230
|
-
let xval = coerceNumberToWasmI64(
|
|
2231
|
-
let yval = coerceNumberToWasmI64(
|
|
2232
|
-
WasmI32.toGrain(reducedInteger(
|
|
2178
|
+
let xval = coerceNumberToWasmI64(value1)
|
|
2179
|
+
let yval = coerceNumberToWasmI64(value2)
|
|
2180
|
+
WasmI32.toGrain(reducedInteger(xval ^ yval)): Number
|
|
2233
2181
|
}
|
|
2234
2182
|
}
|
|
2235
2183
|
|
|
2184
|
+
/**
|
|
2185
|
+
* Shifts the bits of the value right by the given number of bits.
|
|
2186
|
+
*
|
|
2187
|
+
* @param value: The value to shift
|
|
2188
|
+
* @param amount: The amount to shift by
|
|
2189
|
+
* @returns The shifted value
|
|
2190
|
+
*
|
|
2191
|
+
* @since v0.3.0
|
|
2192
|
+
* @history v0.2.0: Originally named `asr`
|
|
2193
|
+
* @history v0.3.0: Renamed to `>>`
|
|
2194
|
+
*/
|
|
2236
2195
|
@unsafe
|
|
2237
|
-
|
|
2238
|
-
|
|
2196
|
+
provide let (>>) = (value: Number, amount: Number) => {
|
|
2197
|
+
use WasmI64.{ (>>) }
|
|
2198
|
+
let xw32 = WasmI32.fromGrain(value)
|
|
2239
2199
|
if (isBigInt(xw32)) {
|
|
2240
|
-
let yval = coerceNumberToWasmI32(
|
|
2200
|
+
let yval = coerceNumberToWasmI32(amount)
|
|
2241
2201
|
// [NOTE]: For BigInts, shrU is the same as shrS because there
|
|
2242
2202
|
// are an *infinite* number of leading ones
|
|
2243
2203
|
WasmI32.toGrain(reducedBigInteger(BI.shrS(xw32, yval))): Number
|
|
2244
2204
|
} else {
|
|
2245
|
-
let xval = coerceNumberToWasmI64(
|
|
2246
|
-
let yval = coerceNumberToWasmI64(
|
|
2247
|
-
WasmI32.toGrain(reducedInteger(
|
|
2205
|
+
let xval = coerceNumberToWasmI64(value)
|
|
2206
|
+
let yval = coerceNumberToWasmI64(amount)
|
|
2207
|
+
WasmI32.toGrain(reducedInteger(xval >> yval)): Number
|
|
2248
2208
|
}
|
|
2249
2209
|
}
|
|
2250
2210
|
|
|
@@ -2254,30 +2214,167 @@ export let (>>) = (x: Number, y: Number) => {
|
|
|
2254
2214
|
// we will fail if attempting to coerce to an int!
|
|
2255
2215
|
|
|
2256
2216
|
@unsafe
|
|
2257
|
-
|
|
2217
|
+
let coerceNumberToShortUint = (x: Number, max32, max64, is8bit) => {
|
|
2218
|
+
use WasmI32.{ (&), (<), (>) }
|
|
2258
2219
|
let x = WasmI32.fromGrain(x)
|
|
2259
|
-
let
|
|
2260
|
-
|
|
2261
|
-
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT32_BOXED_NUM_TAG)
|
|
2262
|
-
) {
|
|
2263
|
-
// avoid extra malloc and prevent x from being freed
|
|
2264
|
-
Memory.incRef(x)
|
|
2265
|
-
x
|
|
2220
|
+
let int32 = if (isSimpleNumber(x)) {
|
|
2221
|
+
untagSimple(x)
|
|
2266
2222
|
} else {
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2223
|
+
let xtag = boxedNumberTag(x)
|
|
2224
|
+
match (xtag) {
|
|
2225
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
2226
|
+
use WasmI64.{ (<), (>) }
|
|
2227
|
+
let int64 = boxedInt64Number(x)
|
|
2228
|
+
if (int64 > max64 || int64 < 0N) {
|
|
2229
|
+
throw Exception.Overflow
|
|
2230
|
+
}
|
|
2231
|
+
WasmI32.wrapI64(int64)
|
|
2232
|
+
},
|
|
2233
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
2234
|
+
BI.toInt32(x)
|
|
2235
|
+
},
|
|
2236
|
+
_ => {
|
|
2237
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
2238
|
+
throw Exception.NumberNotIntlike
|
|
2239
|
+
},
|
|
2240
|
+
}
|
|
2271
2241
|
}
|
|
2272
|
-
|
|
2242
|
+
if (int32 > max32 || int32 < 0n) {
|
|
2243
|
+
throw Exception.Overflow
|
|
2244
|
+
}
|
|
2245
|
+
if (is8bit) int32 & 0xffffn else int32 & 0xffffn
|
|
2273
2246
|
}
|
|
2274
2247
|
|
|
2275
2248
|
@unsafe
|
|
2276
|
-
|
|
2249
|
+
let coerceNumberToShortInt = (x: Number, min32, max32, min64, max64, is8bit) => {
|
|
2250
|
+
use WasmI32.{ (<), (>) }
|
|
2277
2251
|
let x = WasmI32.fromGrain(x)
|
|
2252
|
+
let int32 = if (isSimpleNumber(x)) {
|
|
2253
|
+
untagSimple(x)
|
|
2254
|
+
} else {
|
|
2255
|
+
let xtag = boxedNumberTag(x)
|
|
2256
|
+
match (xtag) {
|
|
2257
|
+
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
2258
|
+
use WasmI64.{ (<), (>) }
|
|
2259
|
+
let int64 = boxedInt64Number(x)
|
|
2260
|
+
if (int64 > max64 || int64 < min64) {
|
|
2261
|
+
throw Exception.Overflow
|
|
2262
|
+
}
|
|
2263
|
+
WasmI32.wrapI64(int64)
|
|
2264
|
+
},
|
|
2265
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
2266
|
+
BI.toInt32(x)
|
|
2267
|
+
},
|
|
2268
|
+
_ => {
|
|
2269
|
+
// rationals are never integral, and we refuse to coerce floats to ints
|
|
2270
|
+
throw Exception.NumberNotIntlike
|
|
2271
|
+
},
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
if (int32 > max32 || int32 < min32) {
|
|
2275
|
+
throw Exception.Overflow
|
|
2276
|
+
}
|
|
2277
|
+
if (is8bit) WasmI32.extendS8(int32) else WasmI32.extendS16(int32)
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
/**
|
|
2281
|
+
* Converts a Number to an Int8.
|
|
2282
|
+
*
|
|
2283
|
+
* @param number: The value to convert
|
|
2284
|
+
* @returns The Number represented as an Int8
|
|
2285
|
+
*
|
|
2286
|
+
* @since v0.6.0
|
|
2287
|
+
*/
|
|
2288
|
+
@unsafe
|
|
2289
|
+
provide let coerceNumberToInt8 = (number: Number) => {
|
|
2290
|
+
let val = coerceNumberToShortInt(
|
|
2291
|
+
number,
|
|
2292
|
+
_SMIN8_I32,
|
|
2293
|
+
_SMAX8_I32,
|
|
2294
|
+
_SMIN8_I64,
|
|
2295
|
+
_SMAX8_I64,
|
|
2296
|
+
true
|
|
2297
|
+
)
|
|
2298
|
+
tagInt8(val)
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
/**
|
|
2302
|
+
* Converts a Number to an Int16.
|
|
2303
|
+
*
|
|
2304
|
+
* @param number: The value to convert
|
|
2305
|
+
* @returns The Number represented as an Int16
|
|
2306
|
+
*
|
|
2307
|
+
* @since v0.6.0
|
|
2308
|
+
*/
|
|
2309
|
+
@unsafe
|
|
2310
|
+
provide let coerceNumberToInt16 = (number: Number) => {
|
|
2311
|
+
let val = coerceNumberToShortInt(
|
|
2312
|
+
number,
|
|
2313
|
+
_SMIN16_I32,
|
|
2314
|
+
_SMAX16_I32,
|
|
2315
|
+
_SMIN16_I64,
|
|
2316
|
+
_SMAX16_I64,
|
|
2317
|
+
false
|
|
2318
|
+
)
|
|
2319
|
+
tagInt16(val)
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
/**
|
|
2323
|
+
* Converts a Number to a Uint8.
|
|
2324
|
+
*
|
|
2325
|
+
* @param number: The value to convert
|
|
2326
|
+
* @returns The Number represented as a Uint8
|
|
2327
|
+
*
|
|
2328
|
+
* @since v0.6.0
|
|
2329
|
+
*/
|
|
2330
|
+
@unsafe
|
|
2331
|
+
provide let coerceNumberToUint8 = (number: Number) => {
|
|
2332
|
+
let val = coerceNumberToShortUint(number, _UMAX8_I32, _UMAX8_I64, true)
|
|
2333
|
+
tagUint8(val)
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
/**
|
|
2337
|
+
* Converts a Number to a Uint16.
|
|
2338
|
+
*
|
|
2339
|
+
* @param number: The value to convert
|
|
2340
|
+
* @returns The Number represented as a Uint16
|
|
2341
|
+
*
|
|
2342
|
+
* @since v0.6.0
|
|
2343
|
+
*/
|
|
2344
|
+
@unsafe
|
|
2345
|
+
provide let coerceNumberToUint16 = (number: Number) => {
|
|
2346
|
+
let val = coerceNumberToShortUint(number, _UMAX16_I32, _UMAX16_I64, false)
|
|
2347
|
+
tagUint16(val)
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
/**
|
|
2351
|
+
* Converts a Number to an Int32.
|
|
2352
|
+
*
|
|
2353
|
+
* @param number: The value to convert
|
|
2354
|
+
* @returns The Number represented as an Int32
|
|
2355
|
+
*
|
|
2356
|
+
* @since v0.2.0
|
|
2357
|
+
*/
|
|
2358
|
+
@unsafe
|
|
2359
|
+
provide let coerceNumberToInt32 = (number: Number) => {
|
|
2360
|
+
let result = newInt32(coerceNumberToWasmI32(number))
|
|
2361
|
+
WasmI32.toGrain(result): Int32
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
/**
|
|
2365
|
+
* Converts a Number to an Int64.
|
|
2366
|
+
*
|
|
2367
|
+
* @param number: The value to convert
|
|
2368
|
+
* @returns The Number represented as an Int64
|
|
2369
|
+
*
|
|
2370
|
+
* @since v0.2.0
|
|
2371
|
+
*/
|
|
2372
|
+
@unsafe
|
|
2373
|
+
provide let coerceNumberToInt64 = (number: Number) => {
|
|
2374
|
+
let x = WasmI32.fromGrain(number)
|
|
2278
2375
|
let result = if (
|
|
2279
2376
|
!isSimpleNumber(x) &&
|
|
2280
|
-
|
|
2377
|
+
boxedNumberTag(x) == Tags._GRAIN_INT64_BOXED_NUM_TAG
|
|
2281
2378
|
) {
|
|
2282
2379
|
// avoid extra malloc and prevent x from being freed
|
|
2283
2380
|
Memory.incRef(x)
|
|
@@ -2290,38 +2387,39 @@ export let coerceNumberToInt64 = (x: Number) => {
|
|
|
2290
2387
|
WasmI32.toGrain(result): Int64
|
|
2291
2388
|
}
|
|
2292
2389
|
|
|
2390
|
+
/**
|
|
2391
|
+
* Converts a Number to a BigInt.
|
|
2392
|
+
*
|
|
2393
|
+
* @param number: The value to convert
|
|
2394
|
+
* @returns The Number represented as a BigInt
|
|
2395
|
+
*
|
|
2396
|
+
* @since v0.5.0
|
|
2397
|
+
*/
|
|
2293
2398
|
@unsafe
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
let result = if (isBigInt(x)) {
|
|
2297
|
-
// avoid extra malloc and prevent x from being freed
|
|
2298
|
-
Memory.incRef(x)
|
|
2299
|
-
x
|
|
2300
|
-
} else {
|
|
2301
|
-
// incRef x to reuse it via WasmI32.toGrain
|
|
2302
|
-
Memory.incRef(x)
|
|
2303
|
-
BI.makeWrappedInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
|
|
2304
|
-
}
|
|
2305
|
-
WasmI32.toGrain(result): BigInt
|
|
2399
|
+
provide let coerceNumberToBigInt = (number: Number) => {
|
|
2400
|
+
WasmI32.toGrain(coerceNumberToBigInt(number)): BigInt
|
|
2306
2401
|
}
|
|
2307
2402
|
|
|
2403
|
+
/**
|
|
2404
|
+
* Converts a Number to a Rational.
|
|
2405
|
+
*
|
|
2406
|
+
* @param number: The value to convert
|
|
2407
|
+
* @returns The Number represented as a Rational
|
|
2408
|
+
*
|
|
2409
|
+
* @since v0.6.0
|
|
2410
|
+
*/
|
|
2308
2411
|
@unsafe
|
|
2309
|
-
|
|
2310
|
-
let x = WasmI32.fromGrain(
|
|
2412
|
+
provide let coerceNumberToRational = (number: Number) => {
|
|
2413
|
+
let x = WasmI32.fromGrain(number)
|
|
2311
2414
|
let result = if (isSimpleNumber(x)) {
|
|
2312
2415
|
newRational(BI.makeWrappedInt32(untagSimple(x)), BI.makeWrappedInt32(1n))
|
|
2313
2416
|
} else {
|
|
2314
2417
|
let tag = boxedNumberTag(x)
|
|
2315
|
-
if (
|
|
2418
|
+
if (tag == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) {
|
|
2316
2419
|
// avoid extra malloc and prevent x from being freed
|
|
2317
2420
|
Memory.incRef(x)
|
|
2318
2421
|
x
|
|
2319
|
-
} else if (
|
|
2320
|
-
newRational(
|
|
2321
|
-
BI.makeWrappedInt32(boxedInt32Number(x)),
|
|
2322
|
-
BI.makeWrappedInt32(1n)
|
|
2323
|
-
)
|
|
2324
|
-
} else if (WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG)) {
|
|
2422
|
+
} else if (tag == Tags._GRAIN_INT64_BOXED_NUM_TAG) {
|
|
2325
2423
|
// incRef x to reuse it via WasmI32.toGrain
|
|
2326
2424
|
Memory.incRef(x)
|
|
2327
2425
|
newRational(
|
|
@@ -2335,30 +2433,34 @@ export let coerceNumberToRational = (x: Number) => {
|
|
|
2335
2433
|
WasmI32.toGrain(result): Rational
|
|
2336
2434
|
}
|
|
2337
2435
|
|
|
2436
|
+
/**
|
|
2437
|
+
* Converts a Number to a Float32.
|
|
2438
|
+
*
|
|
2439
|
+
* @param number: The value to convert
|
|
2440
|
+
* @returns The Number represented as a Float32
|
|
2441
|
+
*
|
|
2442
|
+
* @since v0.2.0
|
|
2443
|
+
*/
|
|
2338
2444
|
@unsafe
|
|
2339
|
-
|
|
2340
|
-
let
|
|
2341
|
-
let result = if (
|
|
2342
|
-
!isSimpleNumber(x) &&
|
|
2343
|
-
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)
|
|
2344
|
-
) {
|
|
2345
|
-
// avoid extra malloc and prevent x from being freed
|
|
2346
|
-
Memory.incRef(x)
|
|
2347
|
-
x
|
|
2348
|
-
} else {
|
|
2349
|
-
// incRef x to reuse it via WasmI32.toGrain
|
|
2350
|
-
Memory.incRef(x)
|
|
2351
|
-
newFloat32(coerceNumberToWasmF32(WasmI32.toGrain(x): Number))
|
|
2352
|
-
}
|
|
2445
|
+
provide let coerceNumberToFloat32 = (number: Number) => {
|
|
2446
|
+
let result = newFloat32(coerceNumberToWasmF32(number))
|
|
2353
2447
|
WasmI32.toGrain(result): Float32
|
|
2354
2448
|
}
|
|
2355
2449
|
|
|
2450
|
+
/**
|
|
2451
|
+
* Converts a Number to a Float64.
|
|
2452
|
+
*
|
|
2453
|
+
* @param number: The value to convert
|
|
2454
|
+
* @returns The Number represented as a Float64
|
|
2455
|
+
*
|
|
2456
|
+
* @since v0.2.0
|
|
2457
|
+
*/
|
|
2356
2458
|
@unsafe
|
|
2357
|
-
|
|
2358
|
-
let x = WasmI32.fromGrain(
|
|
2459
|
+
provide let coerceNumberToFloat64 = (number: Number) => {
|
|
2460
|
+
let x = WasmI32.fromGrain(number)
|
|
2359
2461
|
let result = if (
|
|
2360
2462
|
!isSimpleNumber(x) &&
|
|
2361
|
-
|
|
2463
|
+
boxedNumberTag(x) == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG
|
|
2362
2464
|
) {
|
|
2363
2465
|
// avoid extra malloc and prevent x from being freed
|
|
2364
2466
|
Memory.incRef(x)
|
|
@@ -2371,55 +2473,156 @@ export let coerceNumberToFloat64 = (x: Number) => {
|
|
|
2371
2473
|
WasmI32.toGrain(result): Float64
|
|
2372
2474
|
}
|
|
2373
2475
|
|
|
2476
|
+
/**
|
|
2477
|
+
* Converts an Int8 to a Number.
|
|
2478
|
+
*
|
|
2479
|
+
* @param value: The value to convert
|
|
2480
|
+
* @returns The Int8 represented as a Number
|
|
2481
|
+
*
|
|
2482
|
+
* @since v0.6.0
|
|
2483
|
+
*/
|
|
2374
2484
|
@unsafe
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
): Number
|
|
2485
|
+
provide let coerceInt8ToNumber = (value: Int8) => {
|
|
2486
|
+
let num = untagInt8(value)
|
|
2487
|
+
WasmI32.toGrain(tagSimple(num)): Number
|
|
2379
2488
|
}
|
|
2380
2489
|
|
|
2490
|
+
/**
|
|
2491
|
+
* Converts an Int16 to a Number.
|
|
2492
|
+
*
|
|
2493
|
+
* @param value: The value to convert
|
|
2494
|
+
* @returns The Int16 represented as a Number
|
|
2495
|
+
*
|
|
2496
|
+
* @since v0.6.0
|
|
2497
|
+
*/
|
|
2381
2498
|
@unsafe
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
): Number
|
|
2499
|
+
provide let coerceInt16ToNumber = (value: Int16) => {
|
|
2500
|
+
let num = untagInt16(value)
|
|
2501
|
+
WasmI32.toGrain(tagSimple(num)): Number
|
|
2386
2502
|
}
|
|
2387
2503
|
|
|
2504
|
+
/**
|
|
2505
|
+
* Converts a Uint8 to a Number.
|
|
2506
|
+
*
|
|
2507
|
+
* @param value: The value to convert
|
|
2508
|
+
* @returns The Uint8 represented as a Number
|
|
2509
|
+
*
|
|
2510
|
+
* @since v0.6.0
|
|
2511
|
+
*/
|
|
2388
2512
|
@unsafe
|
|
2389
|
-
|
|
2390
|
-
let
|
|
2513
|
+
provide let coerceUint8ToNumber = (value: Uint8) => {
|
|
2514
|
+
let num = untagUint8(value)
|
|
2515
|
+
WasmI32.toGrain(tagSimple(num)): Number
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
/**
|
|
2519
|
+
* Converts a Uint16 to a Number.
|
|
2520
|
+
*
|
|
2521
|
+
* @param value: The value to convert
|
|
2522
|
+
* @returns The Uint16 represented as a Number
|
|
2523
|
+
*
|
|
2524
|
+
* @since v0.6.0
|
|
2525
|
+
*/
|
|
2526
|
+
@unsafe
|
|
2527
|
+
provide let coerceUint16ToNumber = (value: Uint16) => {
|
|
2528
|
+
let num = untagUint16(value)
|
|
2529
|
+
WasmI32.toGrain(tagSimple(num)): Number
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
/**
|
|
2533
|
+
* Converts an Int32 to a Number.
|
|
2534
|
+
*
|
|
2535
|
+
* @param value: The value to convert
|
|
2536
|
+
* @returns The Int32 represented as a Number
|
|
2537
|
+
*
|
|
2538
|
+
* @since v0.2.0
|
|
2539
|
+
*/
|
|
2540
|
+
@unsafe
|
|
2541
|
+
provide let coerceInt32ToNumber = (value: Int32) => {
|
|
2542
|
+
let x = WasmI32.load(WasmI32.fromGrain(value), 4n)
|
|
2543
|
+
let result = reducedInteger(WasmI64.extendI32S(x))
|
|
2544
|
+
WasmI32.toGrain(result): Number
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
/**
|
|
2548
|
+
* Converts an Int64 to a Number.
|
|
2549
|
+
*
|
|
2550
|
+
* @param value: The value to convert
|
|
2551
|
+
* @returns The Int64 represented as a Number
|
|
2552
|
+
*
|
|
2553
|
+
* @since v0.2.0
|
|
2554
|
+
*/
|
|
2555
|
+
@unsafe
|
|
2556
|
+
provide let coerceInt64ToNumber = (value: Int64) => {
|
|
2557
|
+
WasmI32.toGrain(reducedInteger(boxedInt64Number(WasmI32.fromGrain(value)))):
|
|
2558
|
+
Number
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
/**
|
|
2562
|
+
* Converts a BigInt to a Number.
|
|
2563
|
+
*
|
|
2564
|
+
* @param num: The value to convert
|
|
2565
|
+
* @returns The BigInt represented as a Number
|
|
2566
|
+
*
|
|
2567
|
+
* @since v0.5.0
|
|
2568
|
+
*/
|
|
2569
|
+
@unsafe
|
|
2570
|
+
provide let coerceBigIntToNumber = (num: BigInt) => {
|
|
2571
|
+
let x = WasmI32.fromGrain(num)
|
|
2391
2572
|
// reducedBigInteger assumes that the bigint is dead,
|
|
2392
2573
|
// but in our case, it is not
|
|
2393
2574
|
Memory.incRef(x)
|
|
2394
2575
|
WasmI32.toGrain(reducedBigInteger(x)): Number
|
|
2395
2576
|
}
|
|
2396
2577
|
|
|
2578
|
+
/**
|
|
2579
|
+
* Converts a Rational to a Number.
|
|
2580
|
+
*
|
|
2581
|
+
* @param rational: The value to convert
|
|
2582
|
+
* @returns The Rational represented as a Number
|
|
2583
|
+
*
|
|
2584
|
+
* @since v0.6.0
|
|
2585
|
+
*/
|
|
2397
2586
|
@unsafe
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
)
|
|
2404
|
-
): Number
|
|
2587
|
+
provide let coerceRationalToNumber = (rational: Rational) => {
|
|
2588
|
+
let x = WasmI32.fromGrain(rational)
|
|
2589
|
+
let denom = boxedRationalDenominator(x)
|
|
2590
|
+
let x = if (BI.eq(denom, BI.makeWrappedInt32(1n))) {
|
|
2591
|
+
boxedRationalNumerator(x)
|
|
2405
2592
|
} else {
|
|
2406
|
-
|
|
2407
|
-
// incRef x to reuse it via WasmI32.toGrain
|
|
2408
|
-
Memory.incRef(x)
|
|
2409
|
-
WasmI32.toGrain(x): Number
|
|
2593
|
+
x
|
|
2410
2594
|
}
|
|
2595
|
+
// incRef x to reuse it via WasmI32.toGrain
|
|
2596
|
+
Memory.incRef(x)
|
|
2597
|
+
WasmI32.toGrain(x): Number
|
|
2411
2598
|
}
|
|
2412
2599
|
|
|
2600
|
+
/**
|
|
2601
|
+
* Converts a Float32 to a Number.
|
|
2602
|
+
*
|
|
2603
|
+
* @param float: The value to convert
|
|
2604
|
+
* @returns The Float32 represented as a Number
|
|
2605
|
+
*
|
|
2606
|
+
* @since v0.2.0
|
|
2607
|
+
*/
|
|
2413
2608
|
@unsafe
|
|
2414
|
-
|
|
2415
|
-
WasmI32.
|
|
2416
|
-
|
|
2417
|
-
): Number
|
|
2609
|
+
provide let coerceFloat32ToNumber = (float: Float32) => {
|
|
2610
|
+
let x = WasmF32.load(WasmI32.fromGrain(float), 4n)
|
|
2611
|
+
let x64 = WasmF64.promoteF32(x)
|
|
2612
|
+
WasmI32.toGrain(newFloat64(x64)): Number
|
|
2418
2613
|
}
|
|
2419
2614
|
|
|
2615
|
+
/**
|
|
2616
|
+
* Converts a Float64 to a Number.
|
|
2617
|
+
*
|
|
2618
|
+
* @param float: The value to convert
|
|
2619
|
+
* @returns The Float64 represented as a Number
|
|
2620
|
+
*
|
|
2621
|
+
* @since v0.2.0
|
|
2622
|
+
*/
|
|
2420
2623
|
@unsafe
|
|
2421
|
-
|
|
2422
|
-
let x = WasmI32.fromGrain(
|
|
2624
|
+
provide let coerceFloat64ToNumber = (float: Float64) => {
|
|
2625
|
+
let x = WasmI32.fromGrain(float)
|
|
2423
2626
|
// incRef x to reuse it via WasmI32.toGrain
|
|
2424
2627
|
Memory.incRef(x)
|
|
2425
2628
|
WasmI32.toGrain(x): Number
|
|
@@ -2428,7 +2631,7 @@ export let coerceFloat64ToNumber = (x: Float64) => {
|
|
|
2428
2631
|
/// USER-EXPOSED CONVERSION FUNCTIONS
|
|
2429
2632
|
|
|
2430
2633
|
@unsafe
|
|
2431
|
-
|
|
2634
|
+
provide let convertExactToInexact = (x: Number) => {
|
|
2432
2635
|
x
|
|
2433
2636
|
}
|
|
2434
2637
|
|
|
@@ -2439,22 +2642,15 @@ let convertInexactToExactHelp = x => {
|
|
|
2439
2642
|
} else {
|
|
2440
2643
|
let tag = boxedNumberTag(x)
|
|
2441
2644
|
if (
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)
|
|
2645
|
+
tag == Tags._GRAIN_INT64_BOXED_NUM_TAG ||
|
|
2646
|
+
tag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG ||
|
|
2647
|
+
tag == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG
|
|
2446
2648
|
) {
|
|
2447
2649
|
Memory.incRef(x)
|
|
2448
2650
|
x
|
|
2449
2651
|
} else {
|
|
2450
2652
|
match (tag) {
|
|
2451
|
-
t when
|
|
2452
|
-
// TODO(#1191): Investigate if BigInt is more accurate
|
|
2453
|
-
reducedInteger(
|
|
2454
|
-
WasmI64.truncF32S(WasmF32.nearest(boxedFloat32Number(x)))
|
|
2455
|
-
)
|
|
2456
|
-
},
|
|
2457
|
-
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
2653
|
+
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
2458
2654
|
// TODO(#1191): Investigate if BigInt is more accurate
|
|
2459
2655
|
reducedInteger(
|
|
2460
2656
|
WasmI64.truncF64S(WasmF64.nearest(boxedFloat64Number(x)))
|
|
@@ -2469,57 +2665,123 @@ let convertInexactToExactHelp = x => {
|
|
|
2469
2665
|
}
|
|
2470
2666
|
|
|
2471
2667
|
@unsafe
|
|
2472
|
-
|
|
2668
|
+
provide let convertInexactToExact = (x: Number) => {
|
|
2473
2669
|
WasmI32.toGrain(convertInexactToExactHelp(WasmI32.fromGrain(x))): Number
|
|
2474
2670
|
}
|
|
2475
2671
|
|
|
2672
|
+
/**
|
|
2673
|
+
* Computes the sum of its operands.
|
|
2674
|
+
*
|
|
2675
|
+
* @param num1: The first operand
|
|
2676
|
+
* @param num2: The second operand
|
|
2677
|
+
* @returns The sum of the two operands
|
|
2678
|
+
*
|
|
2679
|
+
* @since v0.1.0
|
|
2680
|
+
*/
|
|
2476
2681
|
@unsafe
|
|
2477
|
-
|
|
2478
|
-
let
|
|
2479
|
-
|
|
2480
|
-
|
|
2682
|
+
provide let (+) = (num1: Number, num2: Number) => {
|
|
2683
|
+
let ret = numberAdd(WasmI32.fromGrain(num1), WasmI32.fromGrain(num2))
|
|
2684
|
+
ignore(num1)
|
|
2685
|
+
ignore(num2)
|
|
2686
|
+
ret
|
|
2481
2687
|
}
|
|
2482
2688
|
|
|
2689
|
+
/**
|
|
2690
|
+
* Computes the difference of its operands.
|
|
2691
|
+
*
|
|
2692
|
+
* @param num1: The first operand
|
|
2693
|
+
* @param num2: The second operand
|
|
2694
|
+
* @returns The difference of the two operands
|
|
2695
|
+
*
|
|
2696
|
+
* @since v0.1.0
|
|
2697
|
+
*/
|
|
2483
2698
|
@unsafe
|
|
2484
|
-
|
|
2485
|
-
let
|
|
2486
|
-
|
|
2487
|
-
|
|
2699
|
+
provide let (-) = (num1: Number, num2: Number) => {
|
|
2700
|
+
let ret = numberSub(WasmI32.fromGrain(num1), WasmI32.fromGrain(num2))
|
|
2701
|
+
ignore(num1)
|
|
2702
|
+
ignore(num2)
|
|
2703
|
+
ret
|
|
2488
2704
|
}
|
|
2489
2705
|
|
|
2706
|
+
/**
|
|
2707
|
+
* Computes the product of its operands.
|
|
2708
|
+
*
|
|
2709
|
+
* @param num1: The first operand
|
|
2710
|
+
* @param num2: The second operand
|
|
2711
|
+
* @returns The product of the two operands
|
|
2712
|
+
*
|
|
2713
|
+
* @since v0.1.0
|
|
2714
|
+
*/
|
|
2490
2715
|
@unsafe
|
|
2491
|
-
|
|
2492
|
-
let
|
|
2493
|
-
|
|
2494
|
-
|
|
2716
|
+
provide let (*) = (num1: Number, num2: Number) => {
|
|
2717
|
+
let ret = numberTimes(WasmI32.fromGrain(num1), WasmI32.fromGrain(num2))
|
|
2718
|
+
ignore(num1)
|
|
2719
|
+
ignore(num2)
|
|
2720
|
+
ret
|
|
2495
2721
|
}
|
|
2496
2722
|
|
|
2723
|
+
/**
|
|
2724
|
+
* Computes the quotient of its operands.
|
|
2725
|
+
*
|
|
2726
|
+
* @param num1: The first operand
|
|
2727
|
+
* @param num2: The second operand
|
|
2728
|
+
* @returns The quotient of the two operands
|
|
2729
|
+
*
|
|
2730
|
+
* @since v0.1.0
|
|
2731
|
+
*/
|
|
2497
2732
|
@unsafe
|
|
2498
|
-
|
|
2499
|
-
let
|
|
2500
|
-
|
|
2501
|
-
|
|
2733
|
+
provide let (/) = (num1: Number, num2: Number) => {
|
|
2734
|
+
let ret = numberDivide(WasmI32.fromGrain(num1), WasmI32.fromGrain(num2))
|
|
2735
|
+
ignore(num1)
|
|
2736
|
+
ignore(num2)
|
|
2737
|
+
ret
|
|
2502
2738
|
}
|
|
2503
2739
|
|
|
2740
|
+
/**
|
|
2741
|
+
* Computes the remainder of the division of the first operand by the second.
|
|
2742
|
+
* The result will have the sign of the second operand.
|
|
2743
|
+
*
|
|
2744
|
+
* @param num1: The first operand
|
|
2745
|
+
* @param num2: The second operand
|
|
2746
|
+
* @returns The modulus of its operands
|
|
2747
|
+
*
|
|
2748
|
+
* @since v0.1.0
|
|
2749
|
+
*/
|
|
2504
2750
|
@unsafe
|
|
2505
|
-
|
|
2506
|
-
let x = WasmI32.fromGrain(
|
|
2507
|
-
let y = WasmI32.fromGrain(
|
|
2751
|
+
provide let (%) = (num1: Number, num2: Number) => {
|
|
2752
|
+
let x = WasmI32.fromGrain(num1)
|
|
2753
|
+
let y = WasmI32.fromGrain(num2)
|
|
2508
2754
|
WasmI32.toGrain(numberMod(x, y)): Number
|
|
2509
2755
|
}
|
|
2510
2756
|
|
|
2511
2757
|
// inc/dec
|
|
2512
2758
|
|
|
2513
|
-
|
|
2514
|
-
|
|
2759
|
+
/**
|
|
2760
|
+
* Increments the value by one.
|
|
2761
|
+
*
|
|
2762
|
+
* @param value: The value to increment
|
|
2763
|
+
* @returns The incremented value
|
|
2764
|
+
*
|
|
2765
|
+
* @since v0.1.0
|
|
2766
|
+
*/
|
|
2767
|
+
provide let incr = value => {
|
|
2768
|
+
value + 1
|
|
2515
2769
|
}
|
|
2516
2770
|
|
|
2517
|
-
|
|
2518
|
-
|
|
2771
|
+
/**
|
|
2772
|
+
* Decrements the value by one.
|
|
2773
|
+
*
|
|
2774
|
+
* @param value: The value to decrement
|
|
2775
|
+
* @returns The decremented value
|
|
2776
|
+
*
|
|
2777
|
+
* @since v0.1.0
|
|
2778
|
+
*/
|
|
2779
|
+
provide let decr = value => {
|
|
2780
|
+
value - 1
|
|
2519
2781
|
}
|
|
2520
2782
|
|
|
2521
2783
|
@unsafe
|
|
2522
|
-
|
|
2784
|
+
provide let isBigInt = x => {
|
|
2523
2785
|
let x = WasmI32.fromGrain(x)
|
|
2524
2786
|
isBigInt(x)
|
|
2525
2787
|
}
|
|
@@ -2544,32 +2806,26 @@ export let isBigInt = x => {
|
|
|
2544
2806
|
* @since v0.5.4
|
|
2545
2807
|
*/
|
|
2546
2808
|
@unsafe
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
let (-) = WasmI32.sub
|
|
2552
|
-
let (+) = WasmI32.add
|
|
2553
|
-
let (<<) = WasmI64.shl
|
|
2809
|
+
provide let scalbn = (x, n) => {
|
|
2810
|
+
use WasmI32.{ (>), (<), (-), (+) }
|
|
2811
|
+
use WasmF64.{ (*) }
|
|
2812
|
+
use WasmI64.{ (<<) }
|
|
2554
2813
|
// Constants
|
|
2555
|
-
let const_0x1p1023 = 8.98847e+307W
|
|
2556
|
-
let const_0x1p_1022 = 2.22507e-308W
|
|
2557
|
-
let const_0x1p53 = 9.0072e+15W
|
|
2558
2814
|
let mut n = n
|
|
2559
2815
|
let mut y = x
|
|
2560
2816
|
if (n > 1023n) {
|
|
2561
|
-
y *=
|
|
2817
|
+
y *= 0x1p1023W
|
|
2562
2818
|
n -= 1023n
|
|
2563
2819
|
if (n > 1023n) {
|
|
2564
|
-
y *=
|
|
2820
|
+
y *= 0x1p1023W
|
|
2565
2821
|
n -= 1023n
|
|
2566
2822
|
if (n > 1023n) n = 1023n
|
|
2567
2823
|
} else if (n < -1023n) {
|
|
2568
2824
|
/* make sure final n < -53 to avoid double rounding in the subnormal range */
|
|
2569
|
-
y *=
|
|
2825
|
+
y *= 0x1p-1022W * 0x1p53W
|
|
2570
2826
|
n += 1022n - 53n
|
|
2571
2827
|
if (n < -1022n) {
|
|
2572
|
-
y *=
|
|
2828
|
+
y *= 0x1p-1022W * 0x1p53W
|
|
2573
2829
|
n += 1022n - 53n
|
|
2574
2830
|
if (n < -1022n) n = -1022n
|
|
2575
2831
|
}
|
|
@@ -2577,3 +2833,421 @@ export let scalbn = (x, n) => {
|
|
|
2577
2833
|
}
|
|
2578
2834
|
y * WasmF64.reinterpretI64(WasmI64.extendI32S(0x3FFn + n) << 52N)
|
|
2579
2835
|
}
|
|
2836
|
+
|
|
2837
|
+
// Exponentiation by squaring https://en.wikipedia.org/wiki/Exponentiation_by_squaring special path for int^int
|
|
2838
|
+
let rec expBySquaring = (y, x, n) => {
|
|
2839
|
+
let (==) = numberEq
|
|
2840
|
+
if (n == 0) {
|
|
2841
|
+
1
|
|
2842
|
+
} else if (n == 1) {
|
|
2843
|
+
x * y
|
|
2844
|
+
} else if (n % 2 == 0) {
|
|
2845
|
+
expBySquaring(y, x * x, n / 2)
|
|
2846
|
+
} else {
|
|
2847
|
+
expBySquaring(x * y, x * x, (n - 1) / 2)
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
// Math.pow is largely based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
2852
|
+
/*
|
|
2853
|
+
* ====================================================
|
|
2854
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
2855
|
+
*
|
|
2856
|
+
* Permission to use, copy, modify, and distribute this
|
|
2857
|
+
* software is freely granted, provided that this notice
|
|
2858
|
+
* is preserved.
|
|
2859
|
+
* ====================================================
|
|
2860
|
+
*/
|
|
2861
|
+
/**
|
|
2862
|
+
* Computes the exponentiation of the given base and power.
|
|
2863
|
+
*
|
|
2864
|
+
* @param base: The base number
|
|
2865
|
+
* @param power: The exponent number
|
|
2866
|
+
* @returns The base raised to the given power
|
|
2867
|
+
*
|
|
2868
|
+
* @since v0.6.0
|
|
2869
|
+
* @history v0.5.4: Originally existed in Number module
|
|
2870
|
+
*/
|
|
2871
|
+
@unsafe
|
|
2872
|
+
provide let (**) = (base, power) => {
|
|
2873
|
+
let (==) = numberEq
|
|
2874
|
+
let (!=) = (x, y) => !numberEq(x, y)
|
|
2875
|
+
let basePtr = WasmI32.fromGrain(base)
|
|
2876
|
+
let powerPtr = WasmI32.fromGrain(power)
|
|
2877
|
+
if (base == 1 && power != 0) {
|
|
2878
|
+
return 1
|
|
2879
|
+
} else if (isInteger(basePtr) && isInteger(powerPtr)) {
|
|
2880
|
+
if (power < 0)
|
|
2881
|
+
return expBySquaring(1, 1 / base, power * -1)
|
|
2882
|
+
else
|
|
2883
|
+
return expBySquaring(1, base, power)
|
|
2884
|
+
} else if (isRational(basePtr) && isInteger(powerPtr)) {
|
|
2885
|
+
// Apply expBySquaring to numerator and denominator
|
|
2886
|
+
let numerator = WasmI32.fromGrain(base)
|
|
2887
|
+
Memory.incRef(numerator)
|
|
2888
|
+
let numerator = WasmI32.toGrain(numerator): Rational
|
|
2889
|
+
let numerator = rationalNumerator(numerator)
|
|
2890
|
+
let denominator = WasmI32.fromGrain(base)
|
|
2891
|
+
Memory.incRef(denominator)
|
|
2892
|
+
let denominator = WasmI32.toGrain(denominator): Rational
|
|
2893
|
+
let denominator = rationalDenominator(denominator)
|
|
2894
|
+
let numerator = if (power < 0)
|
|
2895
|
+
expBySquaring(1, 1 / numerator, power * -1)
|
|
2896
|
+
else
|
|
2897
|
+
expBySquaring(1, numerator, power)
|
|
2898
|
+
let denominator = if (power < 0)
|
|
2899
|
+
expBySquaring(1, 1 / denominator, power * -1)
|
|
2900
|
+
else
|
|
2901
|
+
expBySquaring(1, denominator, power)
|
|
2902
|
+
return numerator / denominator
|
|
2903
|
+
} else {
|
|
2904
|
+
// Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
2905
|
+
use WasmF64.{ (==), (!=), (<=), (/), (*), (+) }
|
|
2906
|
+
let x = coerceNumberToWasmF64(base)
|
|
2907
|
+
let y = coerceNumberToWasmF64(power)
|
|
2908
|
+
// Fast paths
|
|
2909
|
+
if (WasmF64.abs(y) <= 2.0W) {
|
|
2910
|
+
if (y == 2.0W) {
|
|
2911
|
+
return WasmI32.toGrain(newFloat64(x * x)): Number
|
|
2912
|
+
} else if (y == 0.5W) {
|
|
2913
|
+
if (x != InfinityW) {
|
|
2914
|
+
return WasmI32.toGrain(newFloat64(WasmF64.abs(WasmF64.sqrt(x)))):
|
|
2915
|
+
Number
|
|
2916
|
+
} else {
|
|
2917
|
+
return Infinity
|
|
2918
|
+
}
|
|
2919
|
+
} else if (y == -1.0W) {
|
|
2920
|
+
return WasmI32.toGrain(newFloat64(1.0W / x)): Number
|
|
2921
|
+
} else if (y == 1.0W) {
|
|
2922
|
+
return WasmI32.toGrain(newFloat64(x)): Number
|
|
2923
|
+
} else if (y == 0.0W) {
|
|
2924
|
+
return NaN
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
// Full calculation
|
|
2928
|
+
let dp_h1 = WasmF64.reinterpretI64(0x3FE2B80340000000N)
|
|
2929
|
+
let dp_l1 = WasmF64.reinterpretI64(0x3E4CFDEB43CFD006N)
|
|
2930
|
+
let two53 = WasmF64.reinterpretI64(0x4340000000000000N)
|
|
2931
|
+
let huge = WasmF64.reinterpretI64(0x7E37E43C8800759CN)
|
|
2932
|
+
let tiny = WasmF64.reinterpretI64(0x01A56E1FC2F8F359N)
|
|
2933
|
+
let l1 = WasmF64.reinterpretI64(0x3FE3333333333303N)
|
|
2934
|
+
let l2 = WasmF64.reinterpretI64(0x3FDB6DB6DB6FABFFN)
|
|
2935
|
+
let l3 = WasmF64.reinterpretI64(0x3FD55555518F264DN)
|
|
2936
|
+
let l4 = WasmF64.reinterpretI64(0x3FD17460A91D4101N)
|
|
2937
|
+
let l5 = WasmF64.reinterpretI64(0x3FCD864A93C9DB65N)
|
|
2938
|
+
let l6 = WasmF64.reinterpretI64(0x3FCA7E284A454EEFN)
|
|
2939
|
+
let p1 = WasmF64.reinterpretI64(0x3FC555555555553EN)
|
|
2940
|
+
let p2 = WasmF64.reinterpretI64(0xBF66C16C16BEBD93N)
|
|
2941
|
+
let p3 = WasmF64.reinterpretI64(0x3F11566AAF25DE2CN)
|
|
2942
|
+
let p4 = WasmF64.reinterpretI64(0xBEBBBD41C5D26BF1N)
|
|
2943
|
+
let p5 = WasmF64.reinterpretI64(0x3E66376972BEA4D0N)
|
|
2944
|
+
let lg2 = WasmF64.reinterpretI64(0x3FE62E42FEFA39EFN)
|
|
2945
|
+
let lg2_h = WasmF64.reinterpretI64(0x3FE62E4300000000N)
|
|
2946
|
+
let lg2_l = WasmF64.reinterpretI64(0xBE205C610CA86C39N)
|
|
2947
|
+
let ovt = WasmF64.reinterpretI64(0x3C971547652B82FEN)
|
|
2948
|
+
let cp = WasmF64.reinterpretI64(0x3FEEC709DC3A03FDN)
|
|
2949
|
+
let cp_h = WasmF64.reinterpretI64(0x3FEEC709E0000000N)
|
|
2950
|
+
let cp_l = WasmF64.reinterpretI64(0xBE3E2FE0145B01F5N)
|
|
2951
|
+
let ivln2 = WasmF64.reinterpretI64(0x3FF71547652B82FEN)
|
|
2952
|
+
let ivln2_h = WasmF64.reinterpretI64(0x3FF7154760000000N)
|
|
2953
|
+
let ivln2_l = WasmF64.reinterpretI64(0x3E54AE0BF85DDF44N)
|
|
2954
|
+
let inv3 = WasmF64.reinterpretI64(0x3FD5555555555555N)
|
|
2955
|
+
use WasmI32.{
|
|
2956
|
+
(==),
|
|
2957
|
+
(!=),
|
|
2958
|
+
(>=),
|
|
2959
|
+
(<=),
|
|
2960
|
+
(&),
|
|
2961
|
+
(|),
|
|
2962
|
+
(>),
|
|
2963
|
+
(<),
|
|
2964
|
+
(<<),
|
|
2965
|
+
(>>),
|
|
2966
|
+
(-),
|
|
2967
|
+
(+),
|
|
2968
|
+
}
|
|
2969
|
+
use WasmI64.{ (>>) as shrSWasmI64 }
|
|
2970
|
+
let u_ = WasmI64.reinterpretF64(x)
|
|
2971
|
+
let hx = WasmI32.wrapI64(shrSWasmI64(u_, 32N))
|
|
2972
|
+
let lx = WasmI32.wrapI64(u_)
|
|
2973
|
+
let u_ = WasmI64.reinterpretF64(y)
|
|
2974
|
+
let hy = WasmI32.wrapI64(shrSWasmI64(u_, 32N))
|
|
2975
|
+
let ly = WasmI32.wrapI64(u_)
|
|
2976
|
+
let mut ix = hx & 0x7FFFFFFFn
|
|
2977
|
+
let iy = hy & 0x7FFFFFFFn
|
|
2978
|
+
if ((iy | ly) == 0n) { // x**0 = 1, even if x is NaN
|
|
2979
|
+
return 1
|
|
2980
|
+
} else if (
|
|
2981
|
+
// Either Argument is Nan
|
|
2982
|
+
ix > 0x7FF00000n ||
|
|
2983
|
+
ix == 0x7FF00000n && lx != 0n ||
|
|
2984
|
+
iy > 0x7FF00000n ||
|
|
2985
|
+
iy == 0x7FF00000n && ly != 0n
|
|
2986
|
+
) {
|
|
2987
|
+
use WasmF64.{ (+) }
|
|
2988
|
+
return WasmI32.toGrain(newFloat64(x + y)): Number
|
|
2989
|
+
}
|
|
2990
|
+
let mut yisint = 0n
|
|
2991
|
+
let mut k = 0n
|
|
2992
|
+
if (hx < 0n) {
|
|
2993
|
+
if (iy >= 0x43400000n) {
|
|
2994
|
+
yisint = 2n
|
|
2995
|
+
} else if (iy >= 0x3FF00000n) {
|
|
2996
|
+
k = (iy >> 20n) - 0x3FFn
|
|
2997
|
+
let mut offset = 0n
|
|
2998
|
+
let mut _ly = 0n
|
|
2999
|
+
if (k > 20n) {
|
|
3000
|
+
offset = 52n - k
|
|
3001
|
+
_ly = ly
|
|
3002
|
+
} else {
|
|
3003
|
+
offset = 20n - k
|
|
3004
|
+
_ly = iy
|
|
3005
|
+
}
|
|
3006
|
+
let jj = _ly >> offset
|
|
3007
|
+
if (jj << offset == _ly) yisint = 2n - (jj & 1n)
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
if (ly == 0n) {
|
|
3011
|
+
if (iy == 0x7FF00000n) { // y is +- inf
|
|
3012
|
+
if ((ix - 0x3FF00000n | lx) == 0n) { // C: (-1)**+-inf is 1, JS: NaN
|
|
3013
|
+
return NaN
|
|
3014
|
+
} else if (ix >= 0x3FF00000n) { // (|x|>1)**+-inf = inf,0
|
|
3015
|
+
if (hy >= 0n)
|
|
3016
|
+
return WasmI32.toGrain(newFloat64(y)): Number
|
|
3017
|
+
else
|
|
3018
|
+
return 0.0
|
|
3019
|
+
} else { // (|x|<1)**+-inf = 0,inf
|
|
3020
|
+
if (hy >= 0n)
|
|
3021
|
+
return 0.0
|
|
3022
|
+
else
|
|
3023
|
+
return WasmI32.toGrain(newFloat64(y * -1.0W)): Number
|
|
3024
|
+
}
|
|
3025
|
+
} else if (iy == 0x3FF00000n) {
|
|
3026
|
+
if (hy >= 0n)
|
|
3027
|
+
return WasmI32.toGrain(newFloat64(x)): Number
|
|
3028
|
+
else
|
|
3029
|
+
return WasmI32.toGrain(newFloat64(1.0W / x)): Number
|
|
3030
|
+
} else if (hy == 0x3FE00000n) {
|
|
3031
|
+
return WasmI32.toGrain(newFloat64(x * x)): Number
|
|
3032
|
+
} else if (hy == 0x3FE00000n) {
|
|
3033
|
+
if (hx >= 0n) {
|
|
3034
|
+
return WasmI32.toGrain(newFloat64(WasmF64.sqrt(x))): Number
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
let mut ax = WasmF64.abs(x)
|
|
3039
|
+
let mut z = 0.0W
|
|
3040
|
+
if (lx == 0n && (ix == 0n || ix == 0x7FF00000n || ix == 0x3FF00000n)) {
|
|
3041
|
+
z = ax
|
|
3042
|
+
if (hy < 0n) z = 1.0W / z
|
|
3043
|
+
if (hx < 0n) {
|
|
3044
|
+
if ((ix - 0x3FF00000n | yisint) == 0n) {
|
|
3045
|
+
use WasmF64.{ (-) }
|
|
3046
|
+
let d = z - z
|
|
3047
|
+
z = d / d
|
|
3048
|
+
} else if (yisint == 1n) {
|
|
3049
|
+
z *= -1.0W
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
return WasmI32.toGrain(newFloat64(z)): Number
|
|
3053
|
+
}
|
|
3054
|
+
let mut s = 1.0W
|
|
3055
|
+
if (hx < 0n) {
|
|
3056
|
+
if (yisint == 0n) {
|
|
3057
|
+
return NaN
|
|
3058
|
+
} else if (yisint == 1n) {
|
|
3059
|
+
s = -1.0W
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
let mut t1 = 0.0W
|
|
3063
|
+
and t2 = 0.0W
|
|
3064
|
+
and p_h = 0.0W
|
|
3065
|
+
and p_l = 0.0W
|
|
3066
|
+
and r = 0.0W
|
|
3067
|
+
and t = 0.0W
|
|
3068
|
+
and u = 0.0W
|
|
3069
|
+
and v = 0.0W
|
|
3070
|
+
and w = 0.0W
|
|
3071
|
+
let mut j = 0n
|
|
3072
|
+
and n = 0n
|
|
3073
|
+
if (iy > 0x41E00000n) {
|
|
3074
|
+
if (iy > 0x43F00000n) {
|
|
3075
|
+
if (ix <= 0x3FEFFFFFn) {
|
|
3076
|
+
let output = if (hy < 0n) huge * huge else tiny * tiny
|
|
3077
|
+
return WasmI32.toGrain(newFloat64(output)): Number
|
|
3078
|
+
} else if (ix >= 0x3FF00000n) {
|
|
3079
|
+
let output = if (hy > 0n) huge * huge else tiny * tiny
|
|
3080
|
+
return WasmI32.toGrain(newFloat64(output)): Number
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
if (ix < 0x3FEFFFFFn) {
|
|
3084
|
+
if (hy < 0n) {
|
|
3085
|
+
return WasmI32.toGrain(newFloat64(s * huge * huge)): Number
|
|
3086
|
+
} else {
|
|
3087
|
+
return WasmI32.toGrain(newFloat64(s * tiny * tiny)): Number
|
|
3088
|
+
}
|
|
3089
|
+
} else if (ix > 0x3FF00000n) {
|
|
3090
|
+
if (hy > 0n) {
|
|
3091
|
+
return WasmI32.toGrain(newFloat64(s * huge * huge)): Number
|
|
3092
|
+
} else {
|
|
3093
|
+
return WasmI32.toGrain(newFloat64(s * tiny * tiny)): Number
|
|
3094
|
+
}
|
|
3095
|
+
} else {
|
|
3096
|
+
use WasmF64.{ (-), (+) }
|
|
3097
|
+
use WasmI64.{ (&) }
|
|
3098
|
+
t = ax - 1.0W
|
|
3099
|
+
w = t * t * (0.5W - t * (inv3 - t * 0.25W))
|
|
3100
|
+
u = ivln2_h * t
|
|
3101
|
+
v = t * ivln2_l - w * ivln2
|
|
3102
|
+
t1 = u + v
|
|
3103
|
+
t1 = WasmF64.reinterpretI64(
|
|
3104
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
3105
|
+
)
|
|
3106
|
+
t2 = v - (t1 - u)
|
|
3107
|
+
}
|
|
3108
|
+
} else {
|
|
3109
|
+
let mut ss = 0.0W
|
|
3110
|
+
and s2 = 0.0W
|
|
3111
|
+
and s_h = 0.0W
|
|
3112
|
+
and s_l = 0.0W
|
|
3113
|
+
and t_h = 0.0W
|
|
3114
|
+
and t_l = 0.0W
|
|
3115
|
+
n = 0n
|
|
3116
|
+
if (ix < 0x00100000n) {
|
|
3117
|
+
use WasmI64.{ (>>>) }
|
|
3118
|
+
ax *= two53
|
|
3119
|
+
n -= 53n
|
|
3120
|
+
ix = WasmI32.wrapI64(WasmI64.reinterpretF64(ax) >>> 32N)
|
|
3121
|
+
}
|
|
3122
|
+
n += (ix >> 20n) - 0x3FFn
|
|
3123
|
+
j = ix & 0x000FFFFFn
|
|
3124
|
+
ix = j | 0x3FF00000n
|
|
3125
|
+
if (j <= 0x3988En) {
|
|
3126
|
+
k = 0n
|
|
3127
|
+
} else if (j < 0xBB67An) {
|
|
3128
|
+
k = 1n
|
|
3129
|
+
} else {
|
|
3130
|
+
k = 0n
|
|
3131
|
+
n += 1n
|
|
3132
|
+
ix -= 0x00100000n
|
|
3133
|
+
}
|
|
3134
|
+
use WasmI64.{ (&), (|), (<<) }
|
|
3135
|
+
ax = WasmF64.reinterpretI64(
|
|
3136
|
+
WasmI64.reinterpretF64(ax) & 0xFFFFFFFFN | WasmI64.extendI32S(ix) << 32N
|
|
3137
|
+
)
|
|
3138
|
+
let bp = if (k != 0n) 1.5W else 1.0W
|
|
3139
|
+
use WasmF64.{ (+), (-) }
|
|
3140
|
+
u = ax - bp
|
|
3141
|
+
v = 1.0W / (ax + bp)
|
|
3142
|
+
ss = u * v
|
|
3143
|
+
s_h = ss
|
|
3144
|
+
s_h = WasmF64.reinterpretI64(
|
|
3145
|
+
WasmI64.reinterpretF64(s_h) & 0xFFFFFFFF00000000N
|
|
3146
|
+
)
|
|
3147
|
+
use WasmI32.{ (+), (|), (<<) as shlWasmI64 }
|
|
3148
|
+
t_h = WasmF64.reinterpretI64(
|
|
3149
|
+
WasmI64.extendI32S(
|
|
3150
|
+
(ix >> 1n | 0x20000000n) + 0x00080000n + shlWasmI64(k, 18n)
|
|
3151
|
+
) <<
|
|
3152
|
+
32N
|
|
3153
|
+
)
|
|
3154
|
+
use WasmF64.{ (+) }
|
|
3155
|
+
t_l = ax - (t_h - bp)
|
|
3156
|
+
s_l = v * (u - s_h * t_h - s_h * t_l)
|
|
3157
|
+
s2 = ss * ss
|
|
3158
|
+
//formatter-ignore
|
|
3159
|
+
r = s2 * s2 * (l1 + s2 * (l2 + s2 * (l3 + s2 * (l4 + s2 * (l5 + s2 * l6)))))
|
|
3160
|
+
r += s_l * (s_h + ss)
|
|
3161
|
+
s2 = s_h * s_h
|
|
3162
|
+
t_h = 3.0W + s2 + r
|
|
3163
|
+
t_h = WasmF64.reinterpretI64(
|
|
3164
|
+
WasmI64.reinterpretF64(t_h) & 0xFFFFFFFF00000000N
|
|
3165
|
+
)
|
|
3166
|
+
t_l = r - (t_h - 3.0W - s2)
|
|
3167
|
+
u = s_h * t_h
|
|
3168
|
+
v = s_l * t_h + t_l * ss
|
|
3169
|
+
p_h = u + v
|
|
3170
|
+
p_h = WasmF64.reinterpretI64(
|
|
3171
|
+
WasmI64.reinterpretF64(p_h) & 0xFFFFFFFF00000000N
|
|
3172
|
+
)
|
|
3173
|
+
p_l = v - (p_h - u)
|
|
3174
|
+
let z_h = cp_h * p_h
|
|
3175
|
+
let dp_l = if (k != 0n) dp_l1 else 0.0W
|
|
3176
|
+
let z_l = cp_l * p_h + p_l * cp + dp_l
|
|
3177
|
+
t = WasmF64.convertI32S(n)
|
|
3178
|
+
let dp_h = if (k != 0n) dp_h1 else 0.0W
|
|
3179
|
+
t1 = z_h + z_l + dp_h + t
|
|
3180
|
+
t1 = WasmF64.reinterpretI64(
|
|
3181
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
3182
|
+
)
|
|
3183
|
+
t2 = z_l - (t1 - t - dp_h - z_h)
|
|
3184
|
+
}
|
|
3185
|
+
use WasmF64.{ (>), (-), (+) }
|
|
3186
|
+
use WasmI64.{ (&), (>>), (<<) }
|
|
3187
|
+
let y1 = WasmF64.reinterpretI64(
|
|
3188
|
+
WasmI64.reinterpretF64(y) & 0xFFFFFFFF00000000N
|
|
3189
|
+
)
|
|
3190
|
+
p_l = (y - y1) * t1 + y * t2
|
|
3191
|
+
p_h = y1 * t1
|
|
3192
|
+
z = p_l + p_h
|
|
3193
|
+
let u_ = WasmI64.reinterpretF64(z)
|
|
3194
|
+
let j = WasmI32.wrapI64(u_ >> 32N)
|
|
3195
|
+
let i = WasmI32.wrapI64(u_)
|
|
3196
|
+
use WasmI32.{ (-) as addWasmI32, (&) }
|
|
3197
|
+
if (j >= 0x40900000n) {
|
|
3198
|
+
if ((addWasmI32(j, 0x40900000n) | i) != 0n) {
|
|
3199
|
+
return WasmI32.toGrain(newFloat64(s * huge * huge)): Number
|
|
3200
|
+
} else if (p_l + ovt > z - p_h) {
|
|
3201
|
+
return WasmI32.toGrain(newFloat64(s * huge * huge)): Number
|
|
3202
|
+
}
|
|
3203
|
+
} else if ((j & 0x7FFFFFFFn) >= 0x4090CC00n) {
|
|
3204
|
+
use WasmF64.{ (<=) }
|
|
3205
|
+
if (addWasmI32(j, 0xC090CC00n | i) != 0n) {
|
|
3206
|
+
return WasmI32.toGrain(newFloat64(s * tiny * tiny)): Number
|
|
3207
|
+
} else if (p_l <= z - p_h) {
|
|
3208
|
+
return WasmI32.toGrain(newFloat64(s * tiny * tiny)): Number
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
use WasmI32.{ (&), (>>), (-), (+), (>), (*), (<<), (^) }
|
|
3212
|
+
let i = j & 0x7FFFFFFFn
|
|
3213
|
+
k = (i >> 20n) - 0x3FFn
|
|
3214
|
+
n = 0n
|
|
3215
|
+
if (i > 0x3FE00000n) {
|
|
3216
|
+
use WasmI64.{ (<<) }
|
|
3217
|
+
n = j + (0x00100000n >> (k + 1n))
|
|
3218
|
+
k = ((n & 0x7FFFFFFFn) >> 20n) - 0x3FFn
|
|
3219
|
+
t = 0.0W
|
|
3220
|
+
t = WasmF64.reinterpretI64(
|
|
3221
|
+
WasmI64.extendI32S(n & (0x000FFFFFn >> k ^ -1n)) << 32N
|
|
3222
|
+
)
|
|
3223
|
+
n = (n & 0x000FFFFFn | 0x00100000n) >> (20n - k)
|
|
3224
|
+
if (j < 0n) n *= -1n
|
|
3225
|
+
use WasmF64.{ (-) }
|
|
3226
|
+
p_h -= t
|
|
3227
|
+
}
|
|
3228
|
+
use WasmI64.{ (&), (|) }
|
|
3229
|
+
use WasmF64.{ (*), (+), (-) }
|
|
3230
|
+
t = p_l + p_h
|
|
3231
|
+
t = WasmF64.reinterpretI64(WasmI64.reinterpretF64(t) & 0xFFFFFFFF00000000N)
|
|
3232
|
+
u = t * lg2_h
|
|
3233
|
+
v = (p_l - (t - p_h)) * lg2 + t * lg2_l
|
|
3234
|
+
z = u + v
|
|
3235
|
+
w = v - (z - u)
|
|
3236
|
+
t = z * z
|
|
3237
|
+
t1 = z - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5))))
|
|
3238
|
+
r = z * t1 / (t1 - 2.0W) - (w + z * w)
|
|
3239
|
+
z = 1.0W - (r - z)
|
|
3240
|
+
use WasmI32.{ (+) }
|
|
3241
|
+
let j = WasmI32.wrapI64(shrSWasmI64(WasmI64.reinterpretF64(z), 32N)) +
|
|
3242
|
+
(n << 20n)
|
|
3243
|
+
if (j >> 20n <= 0n) {
|
|
3244
|
+
z = scalbn(z, n)
|
|
3245
|
+
} else {
|
|
3246
|
+
use WasmI64.{ (<<) }
|
|
3247
|
+
z = WasmF64.reinterpretI64(
|
|
3248
|
+
WasmI64.reinterpretF64(z) & 0xFFFFFFFFN | WasmI64.extendI32S(j) << 32N
|
|
3249
|
+
)
|
|
3250
|
+
}
|
|
3251
|
+
return WasmI32.toGrain(newFloat64(s * z)): Number
|
|
3252
|
+
}
|
|
3253
|
+
}
|