@grain/stdlib 0.5.2 → 0.5.4
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 +59 -0
- package/array.gr +61 -1
- package/array.md +113 -0
- package/bigint.md +30 -30
- package/buffer.gr +24 -22
- package/char.gr +2 -2
- package/float32.md +3 -3
- package/float64.md +3 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +360 -0
- package/immutablepriorityqueue.md +291 -0
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/list.gr +75 -2
- package/list.md +110 -0
- package/map.gr +1 -2
- package/marshal.gr +1058 -0
- package/marshal.md +76 -0
- package/number.gr +689 -23
- package/number.md +362 -27
- package/package.json +1 -1
- package/pervasives.gr +16 -5
- package/pervasives.md +28 -0
- package/priorityqueue.gr +261 -0
- package/priorityqueue.md +309 -0
- package/queue.gr +14 -1
- package/queue.md +16 -1
- package/regex.gr +90 -67
- package/runtime/bigint.gr +4 -4
- package/runtime/compare.gr +179 -0
- package/runtime/compare.md +6 -0
- package/runtime/equal.gr +3 -3
- package/runtime/exception.gr +9 -5
- package/runtime/exception.md +8 -2
- package/runtime/gc.gr +2 -1
- package/runtime/malloc.gr +1 -3
- package/runtime/numberUtils.gr +11 -11
- package/runtime/numbers.gr +423 -100
- package/runtime/numbers.md +50 -0
- package/runtime/string.gr +4 -2
- package/set.gr +26 -27
- package/stack.gr +12 -0
- package/stack.md +15 -0
- package/string.gr +409 -53
- package/string.md +164 -1
- package/sys/file.gr +4 -4
- package/sys/file.md +3 -3
- package/sys/process.gr +3 -3
- package/sys/process.md +3 -3
- package/sys/random.gr +2 -2
- package/sys/random.md +2 -2
- package/sys/time.gr +2 -2
- package/sys/time.md +2 -2
package/number.gr
CHANGED
|
@@ -13,33 +13,51 @@ import {
|
|
|
13
13
|
coerceNumberToWasmF64,
|
|
14
14
|
reducedInteger,
|
|
15
15
|
isFloat,
|
|
16
|
+
isInteger,
|
|
17
|
+
isRational,
|
|
16
18
|
isBoxedNumber,
|
|
19
|
+
scalbn,
|
|
17
20
|
} from "runtime/numbers"
|
|
18
21
|
import { parseInt } from "runtime/stringUtils"
|
|
19
22
|
import { newFloat64, newInt64 } from "runtime/dataStructures"
|
|
20
23
|
import Tags from "runtime/unsafe/tags"
|
|
24
|
+
import Exception from "runtime/exception"
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
27
|
* @section Constants: Number constant values.
|
|
24
28
|
*/
|
|
25
29
|
|
|
30
|
+
/**
|
|
31
|
+
* NaN represented as a Number value.
|
|
32
|
+
*
|
|
33
|
+
* @since v0.5.4
|
|
34
|
+
*/
|
|
35
|
+
export let nan = 0.0 / 0.0
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Infinity represented as a Number value.
|
|
39
|
+
*
|
|
40
|
+
* @since v0.5.4
|
|
41
|
+
*/
|
|
42
|
+
export let infinity = 1.0 / 0.0
|
|
43
|
+
|
|
26
44
|
/**
|
|
27
45
|
* Pi represented as a Number value.
|
|
28
|
-
*
|
|
46
|
+
*
|
|
29
47
|
* @since v0.5.2
|
|
30
48
|
*/
|
|
31
49
|
export let pi = 3.141592653589793
|
|
32
50
|
|
|
33
51
|
/**
|
|
34
52
|
* Tau represented as a Number value.
|
|
35
|
-
*
|
|
53
|
+
*
|
|
36
54
|
* @since v0.5.2
|
|
37
55
|
*/
|
|
38
56
|
export let tau = 6.283185307179586
|
|
39
57
|
|
|
40
58
|
/**
|
|
41
59
|
* Euler's number represented as a Number value.
|
|
42
|
-
*
|
|
60
|
+
*
|
|
43
61
|
* @since v0.5.2
|
|
44
62
|
*/
|
|
45
63
|
export let e = 2.718281828459045
|
|
@@ -92,6 +110,464 @@ export let mul = (*)
|
|
|
92
110
|
*/
|
|
93
111
|
export let div = (/)
|
|
94
112
|
|
|
113
|
+
// Exponentiation by squaring https://en.wikipedia.org/wiki/Exponentiation_by_squaring special path for int^int
|
|
114
|
+
let rec expBySquaring = (y, x, n) => {
|
|
115
|
+
if (n == 0) {
|
|
116
|
+
1
|
|
117
|
+
} else if (n == 1) {
|
|
118
|
+
x * y
|
|
119
|
+
} else if (n % 2 == 0) {
|
|
120
|
+
expBySquaring(y, x * x, n / 2)
|
|
121
|
+
} else {
|
|
122
|
+
expBySquaring(x * y, x * x, (n - 1) / 2)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Math.pow is largely based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
127
|
+
/*
|
|
128
|
+
* ====================================================
|
|
129
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
130
|
+
*
|
|
131
|
+
* Permission to use, copy, modify, and distribute this
|
|
132
|
+
* software is freely granted, provided that this notice
|
|
133
|
+
* is preserved.
|
|
134
|
+
* ====================================================
|
|
135
|
+
*/
|
|
136
|
+
/**
|
|
137
|
+
* Computes the exponentiation of the given base and power.
|
|
138
|
+
*
|
|
139
|
+
* @param base: The base number
|
|
140
|
+
* @param power: The exponent number
|
|
141
|
+
* @returns The base raised to the given power
|
|
142
|
+
*
|
|
143
|
+
* @since v0.5.4
|
|
144
|
+
*/
|
|
145
|
+
@unsafe
|
|
146
|
+
export let pow = (base, power) => {
|
|
147
|
+
// TODO(#1476): Move this into runtime/numbers.gr
|
|
148
|
+
if (base == 1 && power != 0) {
|
|
149
|
+
1
|
|
150
|
+
} else if (
|
|
151
|
+
isInteger(WasmI32.fromGrain(base)) && isInteger(WasmI32.fromGrain(power))
|
|
152
|
+
) {
|
|
153
|
+
if (power < 0) expBySquaring(1, 1 / base, power * -1)
|
|
154
|
+
else expBySquaring(1, base, power)
|
|
155
|
+
} else {
|
|
156
|
+
// TODO(#553): Refactor once we have early return
|
|
157
|
+
// Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
158
|
+
let (==) = WasmF64.eq
|
|
159
|
+
let (!=) = WasmF64.ne
|
|
160
|
+
let (<=) = WasmF64.le
|
|
161
|
+
let (/) = WasmF64.div
|
|
162
|
+
let (*) = WasmF64.mul
|
|
163
|
+
let (+) = WasmF64.add
|
|
164
|
+
// Constants
|
|
165
|
+
let infinity = 1.0W / 0.0W
|
|
166
|
+
let nan = 0.0W / 0.0W
|
|
167
|
+
let x = coerceNumberToWasmF64(base)
|
|
168
|
+
let y = coerceNumberToWasmF64(power)
|
|
169
|
+
let mut foundOutput = false, output = 0.0W
|
|
170
|
+
// Fast paths
|
|
171
|
+
if (WasmF64.abs(y) <= 2.0W) {
|
|
172
|
+
if (y == 2.0W) {
|
|
173
|
+
foundOutput = true
|
|
174
|
+
output = x * x
|
|
175
|
+
} else if (y == 0.5W) {
|
|
176
|
+
foundOutput = true
|
|
177
|
+
if (x != infinity) output = WasmF64.abs(WasmF64.sqrt(x))
|
|
178
|
+
else output = infinity
|
|
179
|
+
} else if (y == -1.0W) {
|
|
180
|
+
foundOutput = true
|
|
181
|
+
output = 1.0W / x
|
|
182
|
+
} else if (y == 1.0W) {
|
|
183
|
+
foundOutput = true
|
|
184
|
+
output = x
|
|
185
|
+
} else if (y == 0.0W) {
|
|
186
|
+
foundOutput = true
|
|
187
|
+
output = nan
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Full calculation
|
|
191
|
+
if (foundOutput) {
|
|
192
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
193
|
+
} else {
|
|
194
|
+
let dp_h1 = WasmF64.reinterpretI64(0x3FE2B80340000000N)
|
|
195
|
+
let dp_l1 = WasmF64.reinterpretI64(0x3E4CFDEB43CFD006N)
|
|
196
|
+
let two53 = WasmF64.reinterpretI64(0x4340000000000000N)
|
|
197
|
+
let huge = WasmF64.reinterpretI64(0x7E37E43C8800759CN)
|
|
198
|
+
let tiny = WasmF64.reinterpretI64(0x01A56E1FC2F8F359N)
|
|
199
|
+
let l1 = WasmF64.reinterpretI64(0x3FE3333333333303N)
|
|
200
|
+
let l2 = WasmF64.reinterpretI64(0x3FDB6DB6DB6FABFFN)
|
|
201
|
+
let l3 = WasmF64.reinterpretI64(0x3FD55555518F264DN)
|
|
202
|
+
let l4 = WasmF64.reinterpretI64(0x3FD17460A91D4101N)
|
|
203
|
+
let l5 = WasmF64.reinterpretI64(0x3FCD864A93C9DB65N)
|
|
204
|
+
let l6 = WasmF64.reinterpretI64(0x3FCA7E284A454EEFN)
|
|
205
|
+
let p1 = WasmF64.reinterpretI64(0x3FC555555555553EN)
|
|
206
|
+
let p2 = WasmF64.reinterpretI64(0xBF66C16C16BEBD93N)
|
|
207
|
+
let p3 = WasmF64.reinterpretI64(0x3F11566AAF25DE2CN)
|
|
208
|
+
let p4 = WasmF64.reinterpretI64(0xBEBBBD41C5D26BF1N)
|
|
209
|
+
let p5 = WasmF64.reinterpretI64(0x3E66376972BEA4D0N)
|
|
210
|
+
let lg2 = WasmF64.reinterpretI64(0x3FE62E42FEFA39EFN)
|
|
211
|
+
let lg2_h = WasmF64.reinterpretI64(0x3FE62E4300000000N)
|
|
212
|
+
let lg2_l = WasmF64.reinterpretI64(0xBE205C610CA86C39N)
|
|
213
|
+
let ovt = WasmF64.reinterpretI64(0x3C971547652B82FEN)
|
|
214
|
+
let cp = WasmF64.reinterpretI64(0x3FEEC709DC3A03FDN)
|
|
215
|
+
let cp_h = WasmF64.reinterpretI64(0x3FEEC709E0000000N)
|
|
216
|
+
let cp_l = WasmF64.reinterpretI64(0xBE3E2FE0145B01F5N)
|
|
217
|
+
let ivln2 = WasmF64.reinterpretI64(0x3FF71547652B82FEN)
|
|
218
|
+
let ivln2_h = WasmF64.reinterpretI64(0x3FF7154760000000N)
|
|
219
|
+
let ivln2_l = WasmF64.reinterpretI64(0x3E54AE0BF85DDF44N)
|
|
220
|
+
let inv3 = WasmF64.reinterpretI64(0x3FD5555555555555N)
|
|
221
|
+
let (==) = WasmI32.eq
|
|
222
|
+
let (!=) = WasmI32.ne
|
|
223
|
+
let (>=) = WasmI32.geS
|
|
224
|
+
let (<=) = WasmI32.leS
|
|
225
|
+
let (&) = WasmI32.and
|
|
226
|
+
let (|) = WasmI32.or
|
|
227
|
+
let (>) = WasmI32.gtS
|
|
228
|
+
let (<) = WasmI32.ltS
|
|
229
|
+
let (<<) = WasmI32.shl
|
|
230
|
+
let (>>) = WasmI32.shrS
|
|
231
|
+
let (-) = WasmI32.sub
|
|
232
|
+
let (+) = WasmI32.add
|
|
233
|
+
let u_ = WasmI64.reinterpretF64(x)
|
|
234
|
+
let hx = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
235
|
+
let lx = WasmI32.wrapI64(u_)
|
|
236
|
+
let u_ = WasmI64.reinterpretF64(y)
|
|
237
|
+
let hy = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
238
|
+
let ly = WasmI32.wrapI64(u_)
|
|
239
|
+
let mut ix = hx & 0x7FFFFFFFn
|
|
240
|
+
let iy = hy & 0x7FFFFFFFn
|
|
241
|
+
if ((iy | ly) == 0n) { // x**0 = 1, even if x is NaN
|
|
242
|
+
1 // return 1
|
|
243
|
+
} else if (
|
|
244
|
+
// Either Argument is Nan
|
|
245
|
+
ix > 0x7FF00000n ||
|
|
246
|
+
ix == 0x7FF00000n && lx != 0n ||
|
|
247
|
+
iy > 0x7FF00000n ||
|
|
248
|
+
iy == 0x7FF00000n && ly != 0n
|
|
249
|
+
) {
|
|
250
|
+
WasmI32.toGrain(newFloat64(WasmF64.add(x, y))): Number
|
|
251
|
+
} else {
|
|
252
|
+
let mut yisint = 0n
|
|
253
|
+
let mut k = 0n
|
|
254
|
+
if (hx < 0n) {
|
|
255
|
+
if (iy >= 0x43400000n) {
|
|
256
|
+
yisint = 2n
|
|
257
|
+
} else if (iy >= 0x3FF00000n) {
|
|
258
|
+
k = (iy >> 20n) - 0x3FFn
|
|
259
|
+
let mut offset = 0n
|
|
260
|
+
let mut _ly = 0n
|
|
261
|
+
if (k > 20n) {
|
|
262
|
+
offset = 52n - k
|
|
263
|
+
_ly = ly
|
|
264
|
+
} else {
|
|
265
|
+
offset = 20n - k
|
|
266
|
+
_ly = iy
|
|
267
|
+
}
|
|
268
|
+
let jj = _ly >> offset
|
|
269
|
+
if (jj << offset == _ly) yisint = 2n - (jj & 1n)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (ly == 0n) {
|
|
273
|
+
if (iy == 0x7FF00000n) { // y is +- inf
|
|
274
|
+
foundOutput = true
|
|
275
|
+
if ((ix - 0x3FF00000n | lx) == 0n) { // C: (-1)**+-inf is 1, JS: NaN
|
|
276
|
+
output = nan
|
|
277
|
+
} else if (ix >= 0x3FF00000n) { // (|x|>1)**+-inf = inf,0
|
|
278
|
+
if (hy >= 0n) output = y else output = 0.0W
|
|
279
|
+
} else { // (|x|<1)**+-inf = 0,inf
|
|
280
|
+
if (hy >= 0n) output = 0.0W else output = y * -1.0W
|
|
281
|
+
}
|
|
282
|
+
} else if (iy == 0x3FF00000n) {
|
|
283
|
+
foundOutput = true
|
|
284
|
+
if (hy >= 0n) output = x else output = 1.0W / x
|
|
285
|
+
} else if (hy == 0x3FE00000n) {
|
|
286
|
+
foundOutput = true
|
|
287
|
+
output = x * x
|
|
288
|
+
} else if (hy == 0x3FE00000n) {
|
|
289
|
+
if (hx >= 0n) {
|
|
290
|
+
foundOutput = true
|
|
291
|
+
output = WasmF64.sqrt(x)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (foundOutput) {
|
|
296
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
297
|
+
} else {
|
|
298
|
+
let mut ax = WasmF64.abs(x)
|
|
299
|
+
let mut z = 0.0W
|
|
300
|
+
if (
|
|
301
|
+
lx == 0n && (ix == 0n || ix == 0x7FF00000n || ix == 0x3FF00000n)
|
|
302
|
+
) {
|
|
303
|
+
z = ax
|
|
304
|
+
if (hy < 0n) z = 1.0W / z
|
|
305
|
+
if (hx < 0n) {
|
|
306
|
+
if ((ix - 0x3FF00000n | yisint) == 0n) {
|
|
307
|
+
let d = WasmF64.sub(z, z)
|
|
308
|
+
z = d / d
|
|
309
|
+
} else if (yisint == 1n) z *= -1.0W
|
|
310
|
+
}
|
|
311
|
+
WasmI32.toGrain(newFloat64(z)): Number
|
|
312
|
+
} else {
|
|
313
|
+
let mut s = 1.0W
|
|
314
|
+
if (hx < 0n) {
|
|
315
|
+
if (yisint == 0n) {
|
|
316
|
+
let d = WasmF64.sub(x, x)
|
|
317
|
+
foundOutput = true
|
|
318
|
+
output = d / d
|
|
319
|
+
} else if (yisint == 1n) s = -1.0W
|
|
320
|
+
}
|
|
321
|
+
if (foundOutput) {
|
|
322
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
323
|
+
} else {
|
|
324
|
+
let mut t1 = 0.0W,
|
|
325
|
+
t2 = 0.0W,
|
|
326
|
+
p_h = 0.0W,
|
|
327
|
+
p_l = 0.0W,
|
|
328
|
+
r = 0.0W,
|
|
329
|
+
t = 0.0W,
|
|
330
|
+
u = 0.0W,
|
|
331
|
+
v = 0.0W,
|
|
332
|
+
w = 0.0W
|
|
333
|
+
let mut j = 0n, n = 0n
|
|
334
|
+
if (iy > 0x41E00000n) {
|
|
335
|
+
if (iy > 0x43F00000n) {
|
|
336
|
+
if (ix <= 0x3FEFFFFFn) {
|
|
337
|
+
foundOutput = true
|
|
338
|
+
if (hy < 0n) output = huge * huge else output = tiny * tiny
|
|
339
|
+
} else if (ix >= 0x3FF00000n) {
|
|
340
|
+
foundOutput = true
|
|
341
|
+
if (hy > 0n) output = huge * huge else output = tiny * tiny
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (!foundOutput) {
|
|
345
|
+
if (ix < 0x3FEFFFFFn) {
|
|
346
|
+
foundOutput = true
|
|
347
|
+
if (hy < 0n) {
|
|
348
|
+
output = s * huge * huge
|
|
349
|
+
} else {
|
|
350
|
+
output = s * tiny * tiny
|
|
351
|
+
}
|
|
352
|
+
} else if (ix > 0x3FF00000n) {
|
|
353
|
+
foundOutput = true
|
|
354
|
+
if (hy > 0n) {
|
|
355
|
+
output = s * huge * huge
|
|
356
|
+
} else {
|
|
357
|
+
output = s * tiny * tiny
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
let (-) = WasmF64.sub
|
|
361
|
+
let (&) = WasmI64.and
|
|
362
|
+
t = ax - 1.0W
|
|
363
|
+
w = t * t * (0.5W - t * (inv3 - t * 0.25W))
|
|
364
|
+
u = ivln2_h * t
|
|
365
|
+
v = t * ivln2_l - w * ivln2
|
|
366
|
+
t1 = WasmF64.add(u, v)
|
|
367
|
+
t1 = WasmF64.reinterpretI64(
|
|
368
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
369
|
+
)
|
|
370
|
+
t2 = v - (t1 - u)
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
let mut ss = 0.0W,
|
|
375
|
+
s2 = 0.0W,
|
|
376
|
+
s_h = 0.0W,
|
|
377
|
+
s_l = 0.0W,
|
|
378
|
+
t_h = 0.0W,
|
|
379
|
+
t_l = 0.0W
|
|
380
|
+
n = 0n
|
|
381
|
+
if (ix < 0x00100000n) {
|
|
382
|
+
let (>>) = WasmI64.shrU
|
|
383
|
+
ax *= two53
|
|
384
|
+
n -= 53n
|
|
385
|
+
ix = WasmI32.wrapI64(WasmI64.reinterpretF64(ax) >> 32N)
|
|
386
|
+
}
|
|
387
|
+
n += (ix >> 20n) - 0x3FFn
|
|
388
|
+
j = ix & 0x000FFFFFn
|
|
389
|
+
ix = j | 0x3FF00000n
|
|
390
|
+
if (j <= 0x3988En) {
|
|
391
|
+
k = 0n
|
|
392
|
+
} else if (j < 0xBB67An) {
|
|
393
|
+
k = 1n
|
|
394
|
+
} else {
|
|
395
|
+
k = 0n
|
|
396
|
+
n += 1n
|
|
397
|
+
ix -= 0x00100000n
|
|
398
|
+
}
|
|
399
|
+
let (&) = WasmI64.and
|
|
400
|
+
let (|) = WasmI64.or
|
|
401
|
+
let (<<) = WasmI64.shl
|
|
402
|
+
ax = WasmF64.reinterpretI64(
|
|
403
|
+
WasmI64.reinterpretF64(ax) & 0xFFFFFFFFN |
|
|
404
|
+
WasmI64.extendI32S(ix) << 32N
|
|
405
|
+
)
|
|
406
|
+
let bp = if (k != 0n) 1.5W else 1.0W
|
|
407
|
+
u = WasmF64.sub(ax, bp)
|
|
408
|
+
v = 1.0W / WasmF64.add(ax, bp)
|
|
409
|
+
ss = u * v
|
|
410
|
+
s_h = ss
|
|
411
|
+
s_h = WasmF64.reinterpretI64(
|
|
412
|
+
WasmI64.reinterpretF64(s_h) & 0xFFFFFFFF00000000N
|
|
413
|
+
)
|
|
414
|
+
t_h = WasmF64.reinterpretI64(
|
|
415
|
+
WasmI64.shl(
|
|
416
|
+
WasmI64.extendI32S(
|
|
417
|
+
WasmI32.or(WasmI32.shrS(ix, 1n), 0x20000000n) +
|
|
418
|
+
0x00080000n +
|
|
419
|
+
WasmI32.shl(k, 18n)
|
|
420
|
+
),
|
|
421
|
+
32N
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
let (-) = WasmF64.sub
|
|
425
|
+
let (+) = WasmF64.add
|
|
426
|
+
t_l = ax - (t_h - bp)
|
|
427
|
+
s_l = v * (u - s_h * t_h - s_h * t_l)
|
|
428
|
+
s2 = ss * ss
|
|
429
|
+
//formatter-ignore
|
|
430
|
+
r = s2 * s2 * (l1 + s2 * (l2 + s2 * (l3 + s2 * (l4 + s2 * (l5 + s2 * l6)))))
|
|
431
|
+
r += s_l * (s_h + ss)
|
|
432
|
+
s2 = s_h * s_h
|
|
433
|
+
t_h = 3.0W + s2 + r
|
|
434
|
+
t_h = WasmF64.reinterpretI64(
|
|
435
|
+
WasmI64.reinterpretF64(t_h) & 0xFFFFFFFF00000000N
|
|
436
|
+
)
|
|
437
|
+
t_l = r - (t_h - 3.0W - s2)
|
|
438
|
+
u = s_h * t_h
|
|
439
|
+
v = s_l * t_h + t_l * ss
|
|
440
|
+
p_h = u + v
|
|
441
|
+
p_h = WasmF64.reinterpretI64(
|
|
442
|
+
WasmI64.reinterpretF64(p_h) & 0xFFFFFFFF00000000N
|
|
443
|
+
)
|
|
444
|
+
p_l = v - (p_h - u)
|
|
445
|
+
let z_h = cp_h * p_h
|
|
446
|
+
let dp_l = if (k != 0n) dp_l1 else 0.0W
|
|
447
|
+
let z_l = cp_l * p_h + p_l * cp + dp_l
|
|
448
|
+
t = WasmF64.convertI32S(n)
|
|
449
|
+
let dp_h = if (k != 0n) dp_h1 else 0.0W
|
|
450
|
+
t1 = z_h + z_l + dp_h + t
|
|
451
|
+
t1 = WasmF64.reinterpretI64(
|
|
452
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
453
|
+
)
|
|
454
|
+
t2 = z_l - (t1 - t - dp_h - z_h)
|
|
455
|
+
}
|
|
456
|
+
if (foundOutput) {
|
|
457
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
458
|
+
} else {
|
|
459
|
+
let (>) = WasmF64.gt
|
|
460
|
+
let (&) = WasmI64.and
|
|
461
|
+
let (-) = WasmF64.sub
|
|
462
|
+
let (+) = WasmF64.add
|
|
463
|
+
let (>>) = WasmI64.shrS
|
|
464
|
+
let y1 = WasmF64.reinterpretI64(
|
|
465
|
+
WasmI64.reinterpretF64(y) & 0xFFFFFFFF00000000N
|
|
466
|
+
)
|
|
467
|
+
p_l = (y - y1) * t1 + y * t2
|
|
468
|
+
p_h = y1 * t1
|
|
469
|
+
z = p_l + p_h
|
|
470
|
+
let u_ = WasmI64.reinterpretF64(z)
|
|
471
|
+
let j = WasmI32.wrapI64(u_ >> 32N)
|
|
472
|
+
let i = WasmI32.wrapI64(u_)
|
|
473
|
+
if (j >= 0x40900000n) {
|
|
474
|
+
if ((WasmI32.sub(j, 0x40900000n) | i) != 0n) {
|
|
475
|
+
foundOutput = true
|
|
476
|
+
output = s * huge * huge
|
|
477
|
+
} else if (p_l + ovt > z - p_h) {
|
|
478
|
+
foundOutput = true
|
|
479
|
+
output = s * huge * huge
|
|
480
|
+
}
|
|
481
|
+
} else if (WasmI32.and(j, 0x7FFFFFFFn) >= 0x4090CC00n) {
|
|
482
|
+
if (WasmI32.sub(j, 0xC090CC00n | i) != 0n) {
|
|
483
|
+
foundOutput = true
|
|
484
|
+
output = s * tiny * tiny
|
|
485
|
+
} else if (WasmF64.le(p_l, z - p_h)) {
|
|
486
|
+
foundOutput = true
|
|
487
|
+
output = s * tiny * tiny
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (foundOutput) {
|
|
491
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
492
|
+
} else {
|
|
493
|
+
let (&) = WasmI32.and
|
|
494
|
+
let (>>) = WasmI32.shrS
|
|
495
|
+
let (-) = WasmI32.sub
|
|
496
|
+
let (+) = WasmI32.add
|
|
497
|
+
let (>) = WasmI32.gtS
|
|
498
|
+
let (*) = WasmI32.mul
|
|
499
|
+
let i = j & 0x7FFFFFFFn
|
|
500
|
+
k = (i >> 20n) - 0x3FFn
|
|
501
|
+
n = 0n
|
|
502
|
+
if (i > 0x3FE00000n) {
|
|
503
|
+
n = j + (0x00100000n >> k + 1n)
|
|
504
|
+
k = ((n & 0x7FFFFFFFn) >> 20n) - 0x3FFn
|
|
505
|
+
t = 0.0W
|
|
506
|
+
t = WasmF64.reinterpretI64(
|
|
507
|
+
WasmI64.shl(
|
|
508
|
+
WasmI64.extendI32S(
|
|
509
|
+
n & WasmI32.xor(0x000FFFFFn >> k, -1n)
|
|
510
|
+
),
|
|
511
|
+
32N
|
|
512
|
+
)
|
|
513
|
+
)
|
|
514
|
+
n = (n & 0x000FFFFFn | 0x00100000n) >> 20n - k
|
|
515
|
+
if (j < 0n) n *= -1n
|
|
516
|
+
p_h = WasmF64.sub(p_h, t)
|
|
517
|
+
}
|
|
518
|
+
let (&) = WasmI64.and
|
|
519
|
+
let (|) = WasmI64.or
|
|
520
|
+
let (*) = WasmF64.mul
|
|
521
|
+
let (-) = WasmF64.sub
|
|
522
|
+
let (+) = WasmF64.add
|
|
523
|
+
t = WasmF64.add(p_l, p_h)
|
|
524
|
+
t = WasmF64.reinterpretI64(
|
|
525
|
+
WasmI64.reinterpretF64(t) & 0xFFFFFFFF00000000N
|
|
526
|
+
)
|
|
527
|
+
u = t * lg2_h
|
|
528
|
+
v = (p_l - (t - p_h)) * lg2 + t * lg2_l
|
|
529
|
+
z = u + v
|
|
530
|
+
w = v - (z - u)
|
|
531
|
+
t = z * z
|
|
532
|
+
t1 = z - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5))))
|
|
533
|
+
r = z * t1 / (t1 - 2.0W) - (w + z * w)
|
|
534
|
+
z = 1.0W - (r - z)
|
|
535
|
+
let j = WasmI32.add(
|
|
536
|
+
WasmI32.wrapI64(
|
|
537
|
+
WasmI64.shrS(WasmI64.reinterpretF64(z), 32N)
|
|
538
|
+
),
|
|
539
|
+
WasmI32.shl(n, 20n)
|
|
540
|
+
)
|
|
541
|
+
if (WasmI32.shrS(j, 20n) <= 0n) {
|
|
542
|
+
z = scalbn(z, n)
|
|
543
|
+
} else {
|
|
544
|
+
z = WasmF64.reinterpretI64(
|
|
545
|
+
WasmI64.reinterpretF64(z) & 0xFFFFFFFFN |
|
|
546
|
+
WasmI64.shl(WasmI64.extendI32S(j), 32N)
|
|
547
|
+
)
|
|
548
|
+
}
|
|
549
|
+
WasmI32.toGrain(newFloat64(s * z)): Number
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Computes the exponentiation of Euler's number to the given power.
|
|
562
|
+
*
|
|
563
|
+
* @param power: The exponent number
|
|
564
|
+
* @returns The `Number.e` value raised to the given power
|
|
565
|
+
*
|
|
566
|
+
* @since v0.5.4
|
|
567
|
+
*/
|
|
568
|
+
export let exp = power => {
|
|
569
|
+
if (power == 0) 1 else pow(e, power)
|
|
570
|
+
}
|
|
95
571
|
/**
|
|
96
572
|
* Computes the square root of its operand.
|
|
97
573
|
*
|
|
@@ -138,8 +614,9 @@ export let sign = x => {
|
|
|
138
614
|
* @returns The smaller of the two operands
|
|
139
615
|
*
|
|
140
616
|
* @since v0.4.0
|
|
617
|
+
* @history v0.5.4: Handle NaN properly
|
|
141
618
|
*/
|
|
142
|
-
export let min = (x: Number, y: Number) => if (y
|
|
619
|
+
export let min = (x: Number, y: Number) => if (compare(x, y) < 0) x else y
|
|
143
620
|
|
|
144
621
|
/**
|
|
145
622
|
* Returns the larger of its operands.
|
|
@@ -149,8 +626,9 @@ export let min = (x: Number, y: Number) => if (y > x) x else y
|
|
|
149
626
|
* @returns The larger of the two operands
|
|
150
627
|
*
|
|
151
628
|
* @since v0.4.0
|
|
629
|
+
* @history v0.5.4: Handle NaN properly
|
|
152
630
|
*/
|
|
153
|
-
export let max = (x: Number, y: Number) => if (x >
|
|
631
|
+
export let max = (x: Number, y: Number) => if (compare(x, y) > 0) x else y
|
|
154
632
|
|
|
155
633
|
/**
|
|
156
634
|
* Rounds its operand up to the next largest integer.
|
|
@@ -159,12 +637,19 @@ export let max = (x: Number, y: Number) => if (x > y) x else y
|
|
|
159
637
|
* @returns The next largest integer of the operand
|
|
160
638
|
*
|
|
161
639
|
* @since v0.4.0
|
|
640
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
162
641
|
*/
|
|
163
642
|
@unsafe
|
|
164
643
|
export let ceil = (x: Number) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
644
|
+
if (x != x) {
|
|
645
|
+
nan
|
|
646
|
+
} else if (x == infinity) {
|
|
647
|
+
infinity
|
|
648
|
+
} else {
|
|
649
|
+
let xval = coerceNumberToWasmF64(x)
|
|
650
|
+
let ceiling = WasmI64.truncF64S(WasmF64.ceil(xval))
|
|
651
|
+
WasmI32.toGrain(reducedInteger(ceiling)): Number
|
|
652
|
+
}
|
|
168
653
|
}
|
|
169
654
|
|
|
170
655
|
/**
|
|
@@ -174,12 +659,19 @@ export let ceil = (x: Number) => {
|
|
|
174
659
|
* @returns The previous integer of the operand
|
|
175
660
|
*
|
|
176
661
|
* @since v0.4.0
|
|
662
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
177
663
|
*/
|
|
178
664
|
@unsafe
|
|
179
665
|
export let floor = (x: Number) => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
666
|
+
if (x != x) {
|
|
667
|
+
nan
|
|
668
|
+
} else if (x == infinity) {
|
|
669
|
+
infinity
|
|
670
|
+
} else {
|
|
671
|
+
let xval = coerceNumberToWasmF64(x)
|
|
672
|
+
let floored = WasmI64.truncF64S(WasmF64.floor(xval))
|
|
673
|
+
WasmI32.toGrain(reducedInteger(floored)): Number
|
|
674
|
+
}
|
|
183
675
|
}
|
|
184
676
|
|
|
185
677
|
/**
|
|
@@ -189,12 +681,19 @@ export let floor = (x: Number) => {
|
|
|
189
681
|
* @returns The integer part of the operand
|
|
190
682
|
*
|
|
191
683
|
* @since v0.4.0
|
|
684
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
192
685
|
*/
|
|
193
686
|
@unsafe
|
|
194
687
|
export let trunc = (x: Number) => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
688
|
+
if (x != x) {
|
|
689
|
+
nan
|
|
690
|
+
} else if (x == infinity) {
|
|
691
|
+
infinity
|
|
692
|
+
} else {
|
|
693
|
+
let xval = coerceNumberToWasmF64(x)
|
|
694
|
+
let trunced = WasmI64.truncF64S(xval)
|
|
695
|
+
WasmI32.toGrain(reducedInteger(trunced)): Number
|
|
696
|
+
}
|
|
198
697
|
}
|
|
199
698
|
|
|
200
699
|
/**
|
|
@@ -204,12 +703,19 @@ export let trunc = (x: Number) => {
|
|
|
204
703
|
* @returns The nearest integer to the operand
|
|
205
704
|
*
|
|
206
705
|
* @since v0.4.0
|
|
706
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
207
707
|
*/
|
|
208
708
|
@unsafe
|
|
209
709
|
export let round = (x: Number) => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
710
|
+
if (x != x) {
|
|
711
|
+
nan
|
|
712
|
+
} else if (x == infinity) {
|
|
713
|
+
infinity
|
|
714
|
+
} else {
|
|
715
|
+
let xval = coerceNumberToWasmF64(x)
|
|
716
|
+
let rounded = WasmI64.truncF64S(WasmF64.nearest(xval))
|
|
717
|
+
WasmI32.toGrain(reducedInteger(rounded)): Number
|
|
718
|
+
}
|
|
213
719
|
}
|
|
214
720
|
|
|
215
721
|
/**
|
|
@@ -232,6 +738,45 @@ export let abs = (x: Number) => if (0 > x) x * -1 else x
|
|
|
232
738
|
*/
|
|
233
739
|
export let neg = (x: Number) => x * -1
|
|
234
740
|
|
|
741
|
+
/**
|
|
742
|
+
* Checks if a number is a floating point value.
|
|
743
|
+
*
|
|
744
|
+
* @param x: The number to check
|
|
745
|
+
* @returns `true` if the value is a floating point number or `false` otherwise
|
|
746
|
+
*
|
|
747
|
+
* @since v0.5.3
|
|
748
|
+
*/
|
|
749
|
+
@unsafe
|
|
750
|
+
export let isFloat = (x: Number) => {
|
|
751
|
+
isFloat(WasmI32.fromGrain(x))
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Checks if a number is an integer.
|
|
756
|
+
*
|
|
757
|
+
* @param x: The number to check
|
|
758
|
+
* @returns `true` if the value is an integer or `false` otherwise
|
|
759
|
+
*
|
|
760
|
+
* @since v0.5.3
|
|
761
|
+
*/
|
|
762
|
+
@unsafe
|
|
763
|
+
export let isInteger = (x: Number) => {
|
|
764
|
+
isInteger(WasmI32.fromGrain(x))
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Checks if a number is a non-integer rational value.
|
|
769
|
+
*
|
|
770
|
+
* @param x: The number to check
|
|
771
|
+
* @returns `true` if the value is a non-integer rational number or `false` otherwise
|
|
772
|
+
*
|
|
773
|
+
* @since v0.5.3
|
|
774
|
+
*/
|
|
775
|
+
@unsafe
|
|
776
|
+
export let isRational = (x: Number) => {
|
|
777
|
+
isRational(WasmI32.fromGrain(x))
|
|
778
|
+
}
|
|
779
|
+
|
|
235
780
|
/**
|
|
236
781
|
* Checks if a number is finite.
|
|
237
782
|
* All values are finite exept for floating point NaN, infinity or negative infinity.
|
|
@@ -376,14 +921,19 @@ let chebyshevSine = (radians: Number) => {
|
|
|
376
921
|
* @returns The computed sine
|
|
377
922
|
*
|
|
378
923
|
* @since v0.5.2
|
|
924
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
379
925
|
*/
|
|
380
926
|
export let sin = (radians: Number) => {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (quot % 2 == 0) {
|
|
384
|
-
chebyshevSine(bounded)
|
|
927
|
+
if (radians != radians || radians == infinity) {
|
|
928
|
+
nan
|
|
385
929
|
} else {
|
|
386
|
-
|
|
930
|
+
let quot = reduceToPiBound(radians)
|
|
931
|
+
let bounded = radians - pi * quot
|
|
932
|
+
if (quot % 2 == 0) {
|
|
933
|
+
chebyshevSine(bounded)
|
|
934
|
+
} else {
|
|
935
|
+
neg(chebyshevSine(bounded))
|
|
936
|
+
}
|
|
387
937
|
}
|
|
388
938
|
}
|
|
389
939
|
|
|
@@ -394,7 +944,123 @@ export let sin = (radians: Number) => {
|
|
|
394
944
|
* @returns The computed cosine
|
|
395
945
|
*
|
|
396
946
|
* @since v0.5.2
|
|
947
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
397
948
|
*/
|
|
398
949
|
export let cos = (radians: Number) => {
|
|
399
|
-
|
|
950
|
+
if (radians != radians || radians == infinity) {
|
|
951
|
+
nan
|
|
952
|
+
} else {
|
|
953
|
+
sin(pi / 2 + radians)
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Computes the tangent of a number (in radians) using Chebyshev polynomials.
|
|
959
|
+
*
|
|
960
|
+
* @param radians: The input in radians
|
|
961
|
+
* @returns The computed tangent
|
|
962
|
+
*
|
|
963
|
+
* @since v0.5.4
|
|
964
|
+
*/
|
|
965
|
+
export let tan = (radians: Number) => {
|
|
966
|
+
if (isNaN(radians) || isInfinite(radians)) {
|
|
967
|
+
nan
|
|
968
|
+
} else {
|
|
969
|
+
sin(radians) / cos(radians)
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Math.gamma implemented using the Lanczos approximation
|
|
974
|
+
// https://en.wikipedia.org/wiki/Lanczos_approximation
|
|
975
|
+
/**
|
|
976
|
+
* Computes the gamma function of a value using Lanczos approximation.
|
|
977
|
+
* Fails when the given value is zero.
|
|
978
|
+
*
|
|
979
|
+
* @param z: The value to interpolate
|
|
980
|
+
* @returns The gamma of the given value
|
|
981
|
+
*
|
|
982
|
+
* @since v0.5.4
|
|
983
|
+
*/
|
|
984
|
+
export let rec gamma = z => {
|
|
985
|
+
if (z == 0) {
|
|
986
|
+
throw Exception.InvalidArgument("Gamma of 0 is undefined")
|
|
987
|
+
} else if (isInteger(z) && z > 0) {
|
|
988
|
+
let mut output = 1
|
|
989
|
+
for (let mut i = 1; i < z; i += 1) {
|
|
990
|
+
output *= i
|
|
991
|
+
}
|
|
992
|
+
output
|
|
993
|
+
} else {
|
|
994
|
+
let mut z = z
|
|
995
|
+
let g = 7
|
|
996
|
+
let c = [>
|
|
997
|
+
0.99999999999980993,
|
|
998
|
+
676.5203681218851,
|
|
999
|
+
-1259.1392167224028,
|
|
1000
|
+
771.32342877765313,
|
|
1001
|
+
-176.61502916214059,
|
|
1002
|
+
12.507343278686905,
|
|
1003
|
+
-0.13857109526572012,
|
|
1004
|
+
9.9843695780195716e-6,
|
|
1005
|
+
1.5056327351493116e-7,
|
|
1006
|
+
]
|
|
1007
|
+
let mut output = 0
|
|
1008
|
+
if (z < 0.5) {
|
|
1009
|
+
output = pi / (sin(pi * z) * gamma(1 - z))
|
|
1010
|
+
} else if (z == 0.5) {
|
|
1011
|
+
// Handle this case separately because it is out of the domain of Number.pow when calculating
|
|
1012
|
+
output = 1.7724538509055159
|
|
1013
|
+
} else {
|
|
1014
|
+
z -= 1
|
|
1015
|
+
let mut x = c[0]
|
|
1016
|
+
for (let mut i = 1; i < g + 2; i += 1) {
|
|
1017
|
+
x += c[i] / (z + i)
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
let t = z + g + 0.5
|
|
1021
|
+
output = sqrt(2 * pi) * pow(t, z + 0.5) * exp(t * -1) * x
|
|
1022
|
+
}
|
|
1023
|
+
if (abs(output) == infinity) infinity else output
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Computes the product of consecutive integers for an integer input and computes the gamma function for non-integer inputs.
|
|
1029
|
+
* Fails if the input is a negative number.
|
|
1030
|
+
*
|
|
1031
|
+
* @param n: The value to factorialize
|
|
1032
|
+
* @returns The factorial of the given value
|
|
1033
|
+
*
|
|
1034
|
+
* @since v0.5.4
|
|
1035
|
+
*/
|
|
1036
|
+
export let rec factorial = n => {
|
|
1037
|
+
if (isInteger(n) && n < 0) gamma(abs(n) + 1) * -1 else if (
|
|
1038
|
+
!isInteger(n) && n < 0
|
|
1039
|
+
) {
|
|
1040
|
+
throw Exception.InvalidArgument(
|
|
1041
|
+
"Cannot compute the factorial of a negative non-integer"
|
|
1042
|
+
)
|
|
1043
|
+
} else {
|
|
1044
|
+
gamma(n + 1)
|
|
1045
|
+
}
|
|
400
1046
|
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Converts degrees to radians.
|
|
1050
|
+
*
|
|
1051
|
+
* @param degrees: The value to convert
|
|
1052
|
+
* @returns The value in radians
|
|
1053
|
+
*
|
|
1054
|
+
* @since v0.5.4
|
|
1055
|
+
*/
|
|
1056
|
+
export let toRadians = degrees => degrees * (pi / 180)
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Converts radians to degrees.
|
|
1060
|
+
*
|
|
1061
|
+
* @param radians: The value to convert
|
|
1062
|
+
* @returns The value in degrees
|
|
1063
|
+
*
|
|
1064
|
+
* @since v0.5.4
|
|
1065
|
+
*/
|
|
1066
|
+
export let toDegrees = radians => radians * (180 / pi)
|