@grain/stdlib 0.5.3 → 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 +38 -0
- package/array.gr +5 -0
- package/array.md +30 -0
- package/char.gr +2 -2
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +33 -5
- package/immutablepriorityqueue.md +44 -1
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/list.gr +2 -2
- package/marshal.gr +4 -4
- package/number.gr +648 -23
- package/number.md +284 -24
- package/package.json +1 -1
- package/priorityqueue.gr +25 -5
- package/priorityqueue.md +30 -0
- package/queue.gr +14 -1
- package/queue.md +16 -1
- package/regex.gr +85 -62
- package/runtime/bigint.gr +4 -4
- package/runtime/compare.gr +2 -1
- package/runtime/equal.gr +2 -1
- 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 +120 -36
- package/runtime/numbers.md +26 -0
- package/runtime/string.gr +4 -2
- package/set.gr +25 -25
- package/stack.gr +12 -0
- package/stack.md +15 -0
- package/string.gr +312 -38
- package/string.md +99 -0
- package/sys/file.gr +1 -1
package/number.gr
CHANGED
|
@@ -16,32 +16,48 @@ import {
|
|
|
16
16
|
isInteger,
|
|
17
17
|
isRational,
|
|
18
18
|
isBoxedNumber,
|
|
19
|
+
scalbn,
|
|
19
20
|
} from "runtime/numbers"
|
|
20
21
|
import { parseInt } from "runtime/stringUtils"
|
|
21
22
|
import { newFloat64, newInt64 } from "runtime/dataStructures"
|
|
22
23
|
import Tags from "runtime/unsafe/tags"
|
|
24
|
+
import Exception from "runtime/exception"
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* @section Constants: Number constant values.
|
|
26
28
|
*/
|
|
27
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
|
+
|
|
28
44
|
/**
|
|
29
45
|
* Pi represented as a Number value.
|
|
30
|
-
*
|
|
46
|
+
*
|
|
31
47
|
* @since v0.5.2
|
|
32
48
|
*/
|
|
33
49
|
export let pi = 3.141592653589793
|
|
34
50
|
|
|
35
51
|
/**
|
|
36
52
|
* Tau represented as a Number value.
|
|
37
|
-
*
|
|
53
|
+
*
|
|
38
54
|
* @since v0.5.2
|
|
39
55
|
*/
|
|
40
56
|
export let tau = 6.283185307179586
|
|
41
57
|
|
|
42
58
|
/**
|
|
43
59
|
* Euler's number represented as a Number value.
|
|
44
|
-
*
|
|
60
|
+
*
|
|
45
61
|
* @since v0.5.2
|
|
46
62
|
*/
|
|
47
63
|
export let e = 2.718281828459045
|
|
@@ -94,6 +110,464 @@ export let mul = (*)
|
|
|
94
110
|
*/
|
|
95
111
|
export let div = (/)
|
|
96
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
|
+
}
|
|
97
571
|
/**
|
|
98
572
|
* Computes the square root of its operand.
|
|
99
573
|
*
|
|
@@ -140,8 +614,9 @@ export let sign = x => {
|
|
|
140
614
|
* @returns The smaller of the two operands
|
|
141
615
|
*
|
|
142
616
|
* @since v0.4.0
|
|
617
|
+
* @history v0.5.4: Handle NaN properly
|
|
143
618
|
*/
|
|
144
|
-
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
|
|
145
620
|
|
|
146
621
|
/**
|
|
147
622
|
* Returns the larger of its operands.
|
|
@@ -151,8 +626,9 @@ export let min = (x: Number, y: Number) => if (y > x) x else y
|
|
|
151
626
|
* @returns The larger of the two operands
|
|
152
627
|
*
|
|
153
628
|
* @since v0.4.0
|
|
629
|
+
* @history v0.5.4: Handle NaN properly
|
|
154
630
|
*/
|
|
155
|
-
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
|
|
156
632
|
|
|
157
633
|
/**
|
|
158
634
|
* Rounds its operand up to the next largest integer.
|
|
@@ -161,12 +637,19 @@ export let max = (x: Number, y: Number) => if (x > y) x else y
|
|
|
161
637
|
* @returns The next largest integer of the operand
|
|
162
638
|
*
|
|
163
639
|
* @since v0.4.0
|
|
640
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
164
641
|
*/
|
|
165
642
|
@unsafe
|
|
166
643
|
export let ceil = (x: Number) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
+
}
|
|
170
653
|
}
|
|
171
654
|
|
|
172
655
|
/**
|
|
@@ -176,12 +659,19 @@ export let ceil = (x: Number) => {
|
|
|
176
659
|
* @returns The previous integer of the operand
|
|
177
660
|
*
|
|
178
661
|
* @since v0.4.0
|
|
662
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
179
663
|
*/
|
|
180
664
|
@unsafe
|
|
181
665
|
export let floor = (x: Number) => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
+
}
|
|
185
675
|
}
|
|
186
676
|
|
|
187
677
|
/**
|
|
@@ -191,12 +681,19 @@ export let floor = (x: Number) => {
|
|
|
191
681
|
* @returns The integer part of the operand
|
|
192
682
|
*
|
|
193
683
|
* @since v0.4.0
|
|
684
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
194
685
|
*/
|
|
195
686
|
@unsafe
|
|
196
687
|
export let trunc = (x: Number) => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
+
}
|
|
200
697
|
}
|
|
201
698
|
|
|
202
699
|
/**
|
|
@@ -206,12 +703,19 @@ export let trunc = (x: Number) => {
|
|
|
206
703
|
* @returns The nearest integer to the operand
|
|
207
704
|
*
|
|
208
705
|
* @since v0.4.0
|
|
706
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
209
707
|
*/
|
|
210
708
|
@unsafe
|
|
211
709
|
export let round = (x: Number) => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
+
}
|
|
215
719
|
}
|
|
216
720
|
|
|
217
721
|
/**
|
|
@@ -417,14 +921,19 @@ let chebyshevSine = (radians: Number) => {
|
|
|
417
921
|
* @returns The computed sine
|
|
418
922
|
*
|
|
419
923
|
* @since v0.5.2
|
|
924
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
420
925
|
*/
|
|
421
926
|
export let sin = (radians: Number) => {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (quot % 2 == 0) {
|
|
425
|
-
chebyshevSine(bounded)
|
|
927
|
+
if (radians != radians || radians == infinity) {
|
|
928
|
+
nan
|
|
426
929
|
} else {
|
|
427
|
-
|
|
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
|
+
}
|
|
428
937
|
}
|
|
429
938
|
}
|
|
430
939
|
|
|
@@ -435,7 +944,123 @@ export let sin = (radians: Number) => {
|
|
|
435
944
|
* @returns The computed cosine
|
|
436
945
|
*
|
|
437
946
|
* @since v0.5.2
|
|
947
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
438
948
|
*/
|
|
439
949
|
export let cos = (radians: Number) => {
|
|
440
|
-
|
|
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
|
+
}
|
|
441
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)
|