@grain/stdlib 0.5.3 → 0.5.5
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 +61 -0
- package/array.gr +65 -57
- package/array.md +54 -6
- package/buffer.gr +71 -1
- package/buffer.md +142 -0
- package/bytes.gr +52 -3
- package/bytes.md +117 -0
- package/char.gr +23 -20
- package/char.md +18 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +44 -16
- package/immutablepriorityqueue.md +44 -1
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/int32.gr +39 -37
- package/int32.md +6 -0
- package/int64.gr +39 -37
- package/int64.md +6 -0
- package/list.gr +33 -24
- package/list.md +39 -10
- package/map.gr +19 -28
- package/marshal.gr +4 -4
- package/number.gr +727 -26
- package/number.md +345 -23
- package/option.gr +30 -26
- package/option.md +12 -0
- package/package.json +1 -1
- package/path.gr +787 -0
- package/path.md +727 -0
- package/pervasives.gr +3 -4
- package/pervasives.md +6 -1
- package/priorityqueue.gr +25 -5
- package/priorityqueue.md +30 -0
- package/queue.gr +22 -7
- package/queue.md +18 -1
- package/regex.gr +161 -65
- package/regex.md +70 -0
- package/result.gr +24 -20
- package/result.md +12 -0
- package/runtime/atof/common.gr +198 -0
- package/runtime/atof/common.md +243 -0
- package/runtime/atof/decimal.gr +663 -0
- package/runtime/atof/decimal.md +59 -0
- package/runtime/atof/lemire.gr +264 -0
- package/runtime/atof/lemire.md +6 -0
- package/runtime/atof/parse.gr +615 -0
- package/runtime/atof/parse.md +12 -0
- package/runtime/atof/slow.gr +238 -0
- package/runtime/atof/slow.md +6 -0
- package/runtime/atof/table.gr +2016 -0
- package/runtime/atof/table.md +12 -0
- package/runtime/{stringUtils.gr → atoi/parse.gr} +1 -1
- package/runtime/{stringUtils.md → atoi/parse.md} +1 -1
- package/runtime/bigint.gr +7 -7
- package/runtime/compare.gr +2 -1
- package/runtime/equal.gr +3 -2
- 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 +13 -13
- package/runtime/numberUtils.md +6 -0
- package/runtime/numbers.gr +123 -39
- package/runtime/numbers.md +26 -0
- package/runtime/string.gr +4 -2
- package/runtime/unsafe/conv.gr +21 -41
- package/runtime/unsafe/conv.md +0 -3
- package/runtime/unsafe/printWasm.gr +4 -40
- package/runtime/utils/printing.gr +3 -3
- package/set.gr +25 -25
- package/stack.gr +14 -0
- package/stack.md +17 -0
- package/string.gr +313 -39
- package/string.md +99 -0
- package/sys/file.gr +1 -1
- package/sys/time.gr +4 -4
package/number.gr
CHANGED
|
@@ -16,32 +16,49 @@ import {
|
|
|
16
16
|
isInteger,
|
|
17
17
|
isRational,
|
|
18
18
|
isBoxedNumber,
|
|
19
|
+
scalbn,
|
|
19
20
|
} from "runtime/numbers"
|
|
20
|
-
import
|
|
21
|
-
import
|
|
21
|
+
import Atoi from "runtime/atoi/parse"
|
|
22
|
+
import Atof from "runtime/atof/parse"
|
|
23
|
+
import { newFloat64, newInt64, allocateString } from "runtime/dataStructures"
|
|
22
24
|
import Tags from "runtime/unsafe/tags"
|
|
25
|
+
import Exception from "runtime/exception"
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
28
|
* @section Constants: Number constant values.
|
|
26
29
|
*/
|
|
27
30
|
|
|
31
|
+
/**
|
|
32
|
+
* NaN represented as a Number value.
|
|
33
|
+
*
|
|
34
|
+
* @since v0.5.4
|
|
35
|
+
*/
|
|
36
|
+
export let nan = 0.0 / 0.0
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Infinity represented as a Number value.
|
|
40
|
+
*
|
|
41
|
+
* @since v0.5.4
|
|
42
|
+
*/
|
|
43
|
+
export let infinity = 1.0 / 0.0
|
|
44
|
+
|
|
28
45
|
/**
|
|
29
46
|
* Pi represented as a Number value.
|
|
30
|
-
*
|
|
47
|
+
*
|
|
31
48
|
* @since v0.5.2
|
|
32
49
|
*/
|
|
33
50
|
export let pi = 3.141592653589793
|
|
34
51
|
|
|
35
52
|
/**
|
|
36
53
|
* Tau represented as a Number value.
|
|
37
|
-
*
|
|
54
|
+
*
|
|
38
55
|
* @since v0.5.2
|
|
39
56
|
*/
|
|
40
57
|
export let tau = 6.283185307179586
|
|
41
58
|
|
|
42
59
|
/**
|
|
43
60
|
* Euler's number represented as a Number value.
|
|
44
|
-
*
|
|
61
|
+
*
|
|
45
62
|
* @since v0.5.2
|
|
46
63
|
*/
|
|
47
64
|
export let e = 2.718281828459045
|
|
@@ -94,6 +111,464 @@ export let mul = (*)
|
|
|
94
111
|
*/
|
|
95
112
|
export let div = (/)
|
|
96
113
|
|
|
114
|
+
// Exponentiation by squaring https://en.wikipedia.org/wiki/Exponentiation_by_squaring special path for int^int
|
|
115
|
+
let rec expBySquaring = (y, x, n) => {
|
|
116
|
+
if (n == 0) {
|
|
117
|
+
1
|
|
118
|
+
} else if (n == 1) {
|
|
119
|
+
x * y
|
|
120
|
+
} else if (n % 2 == 0) {
|
|
121
|
+
expBySquaring(y, x * x, n / 2)
|
|
122
|
+
} else {
|
|
123
|
+
expBySquaring(x * y, x * x, (n - 1) / 2)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Math.pow is largely based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
128
|
+
/*
|
|
129
|
+
* ====================================================
|
|
130
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
131
|
+
*
|
|
132
|
+
* Permission to use, copy, modify, and distribute this
|
|
133
|
+
* software is freely granted, provided that this notice
|
|
134
|
+
* is preserved.
|
|
135
|
+
* ====================================================
|
|
136
|
+
*/
|
|
137
|
+
/**
|
|
138
|
+
* Computes the exponentiation of the given base and power.
|
|
139
|
+
*
|
|
140
|
+
* @param base: The base number
|
|
141
|
+
* @param power: The exponent number
|
|
142
|
+
* @returns The base raised to the given power
|
|
143
|
+
*
|
|
144
|
+
* @since v0.5.4
|
|
145
|
+
*/
|
|
146
|
+
@unsafe
|
|
147
|
+
export let pow = (base, power) => {
|
|
148
|
+
// TODO(#1476): Move this into runtime/numbers.gr
|
|
149
|
+
if (base == 1 && power != 0) {
|
|
150
|
+
1
|
|
151
|
+
} else if (
|
|
152
|
+
isInteger(WasmI32.fromGrain(base)) && isInteger(WasmI32.fromGrain(power))
|
|
153
|
+
) {
|
|
154
|
+
if (power < 0) expBySquaring(1, 1 / base, power * -1)
|
|
155
|
+
else expBySquaring(1, base, power)
|
|
156
|
+
} else {
|
|
157
|
+
// TODO(#553): Refactor once we have early return
|
|
158
|
+
// Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
159
|
+
let (==) = WasmF64.eq
|
|
160
|
+
let (!=) = WasmF64.ne
|
|
161
|
+
let (<=) = WasmF64.le
|
|
162
|
+
let (/) = WasmF64.div
|
|
163
|
+
let (*) = WasmF64.mul
|
|
164
|
+
let (+) = WasmF64.add
|
|
165
|
+
// Constants
|
|
166
|
+
let infinity = 1.0W / 0.0W
|
|
167
|
+
let nan = 0.0W / 0.0W
|
|
168
|
+
let x = coerceNumberToWasmF64(base)
|
|
169
|
+
let y = coerceNumberToWasmF64(power)
|
|
170
|
+
let mut foundOutput = false, output = 0.0W
|
|
171
|
+
// Fast paths
|
|
172
|
+
if (WasmF64.abs(y) <= 2.0W) {
|
|
173
|
+
if (y == 2.0W) {
|
|
174
|
+
foundOutput = true
|
|
175
|
+
output = x * x
|
|
176
|
+
} else if (y == 0.5W) {
|
|
177
|
+
foundOutput = true
|
|
178
|
+
if (x != infinity) output = WasmF64.abs(WasmF64.sqrt(x))
|
|
179
|
+
else output = infinity
|
|
180
|
+
} else if (y == -1.0W) {
|
|
181
|
+
foundOutput = true
|
|
182
|
+
output = 1.0W / x
|
|
183
|
+
} else if (y == 1.0W) {
|
|
184
|
+
foundOutput = true
|
|
185
|
+
output = x
|
|
186
|
+
} else if (y == 0.0W) {
|
|
187
|
+
foundOutput = true
|
|
188
|
+
output = nan
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Full calculation
|
|
192
|
+
if (foundOutput) {
|
|
193
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
194
|
+
} else {
|
|
195
|
+
let dp_h1 = WasmF64.reinterpretI64(0x3FE2B80340000000N)
|
|
196
|
+
let dp_l1 = WasmF64.reinterpretI64(0x3E4CFDEB43CFD006N)
|
|
197
|
+
let two53 = WasmF64.reinterpretI64(0x4340000000000000N)
|
|
198
|
+
let huge = WasmF64.reinterpretI64(0x7E37E43C8800759CN)
|
|
199
|
+
let tiny = WasmF64.reinterpretI64(0x01A56E1FC2F8F359N)
|
|
200
|
+
let l1 = WasmF64.reinterpretI64(0x3FE3333333333303N)
|
|
201
|
+
let l2 = WasmF64.reinterpretI64(0x3FDB6DB6DB6FABFFN)
|
|
202
|
+
let l3 = WasmF64.reinterpretI64(0x3FD55555518F264DN)
|
|
203
|
+
let l4 = WasmF64.reinterpretI64(0x3FD17460A91D4101N)
|
|
204
|
+
let l5 = WasmF64.reinterpretI64(0x3FCD864A93C9DB65N)
|
|
205
|
+
let l6 = WasmF64.reinterpretI64(0x3FCA7E284A454EEFN)
|
|
206
|
+
let p1 = WasmF64.reinterpretI64(0x3FC555555555553EN)
|
|
207
|
+
let p2 = WasmF64.reinterpretI64(0xBF66C16C16BEBD93N)
|
|
208
|
+
let p3 = WasmF64.reinterpretI64(0x3F11566AAF25DE2CN)
|
|
209
|
+
let p4 = WasmF64.reinterpretI64(0xBEBBBD41C5D26BF1N)
|
|
210
|
+
let p5 = WasmF64.reinterpretI64(0x3E66376972BEA4D0N)
|
|
211
|
+
let lg2 = WasmF64.reinterpretI64(0x3FE62E42FEFA39EFN)
|
|
212
|
+
let lg2_h = WasmF64.reinterpretI64(0x3FE62E4300000000N)
|
|
213
|
+
let lg2_l = WasmF64.reinterpretI64(0xBE205C610CA86C39N)
|
|
214
|
+
let ovt = WasmF64.reinterpretI64(0x3C971547652B82FEN)
|
|
215
|
+
let cp = WasmF64.reinterpretI64(0x3FEEC709DC3A03FDN)
|
|
216
|
+
let cp_h = WasmF64.reinterpretI64(0x3FEEC709E0000000N)
|
|
217
|
+
let cp_l = WasmF64.reinterpretI64(0xBE3E2FE0145B01F5N)
|
|
218
|
+
let ivln2 = WasmF64.reinterpretI64(0x3FF71547652B82FEN)
|
|
219
|
+
let ivln2_h = WasmF64.reinterpretI64(0x3FF7154760000000N)
|
|
220
|
+
let ivln2_l = WasmF64.reinterpretI64(0x3E54AE0BF85DDF44N)
|
|
221
|
+
let inv3 = WasmF64.reinterpretI64(0x3FD5555555555555N)
|
|
222
|
+
let (==) = WasmI32.eq
|
|
223
|
+
let (!=) = WasmI32.ne
|
|
224
|
+
let (>=) = WasmI32.geS
|
|
225
|
+
let (<=) = WasmI32.leS
|
|
226
|
+
let (&) = WasmI32.and
|
|
227
|
+
let (|) = WasmI32.or
|
|
228
|
+
let (>) = WasmI32.gtS
|
|
229
|
+
let (<) = WasmI32.ltS
|
|
230
|
+
let (<<) = WasmI32.shl
|
|
231
|
+
let (>>) = WasmI32.shrS
|
|
232
|
+
let (-) = WasmI32.sub
|
|
233
|
+
let (+) = WasmI32.add
|
|
234
|
+
let u_ = WasmI64.reinterpretF64(x)
|
|
235
|
+
let hx = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
236
|
+
let lx = WasmI32.wrapI64(u_)
|
|
237
|
+
let u_ = WasmI64.reinterpretF64(y)
|
|
238
|
+
let hy = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
239
|
+
let ly = WasmI32.wrapI64(u_)
|
|
240
|
+
let mut ix = hx & 0x7FFFFFFFn
|
|
241
|
+
let iy = hy & 0x7FFFFFFFn
|
|
242
|
+
if ((iy | ly) == 0n) { // x**0 = 1, even if x is NaN
|
|
243
|
+
1 // return 1
|
|
244
|
+
} else if (
|
|
245
|
+
// Either Argument is Nan
|
|
246
|
+
ix > 0x7FF00000n ||
|
|
247
|
+
ix == 0x7FF00000n && lx != 0n ||
|
|
248
|
+
iy > 0x7FF00000n ||
|
|
249
|
+
iy == 0x7FF00000n && ly != 0n
|
|
250
|
+
) {
|
|
251
|
+
WasmI32.toGrain(newFloat64(WasmF64.add(x, y))): Number
|
|
252
|
+
} else {
|
|
253
|
+
let mut yisint = 0n
|
|
254
|
+
let mut k = 0n
|
|
255
|
+
if (hx < 0n) {
|
|
256
|
+
if (iy >= 0x43400000n) {
|
|
257
|
+
yisint = 2n
|
|
258
|
+
} else if (iy >= 0x3FF00000n) {
|
|
259
|
+
k = (iy >> 20n) - 0x3FFn
|
|
260
|
+
let mut offset = 0n
|
|
261
|
+
let mut _ly = 0n
|
|
262
|
+
if (k > 20n) {
|
|
263
|
+
offset = 52n - k
|
|
264
|
+
_ly = ly
|
|
265
|
+
} else {
|
|
266
|
+
offset = 20n - k
|
|
267
|
+
_ly = iy
|
|
268
|
+
}
|
|
269
|
+
let jj = _ly >> offset
|
|
270
|
+
if (jj << offset == _ly) yisint = 2n - (jj & 1n)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (ly == 0n) {
|
|
274
|
+
if (iy == 0x7FF00000n) { // y is +- inf
|
|
275
|
+
foundOutput = true
|
|
276
|
+
if ((ix - 0x3FF00000n | lx) == 0n) { // C: (-1)**+-inf is 1, JS: NaN
|
|
277
|
+
output = nan
|
|
278
|
+
} else if (ix >= 0x3FF00000n) { // (|x|>1)**+-inf = inf,0
|
|
279
|
+
if (hy >= 0n) output = y else output = 0.0W
|
|
280
|
+
} else { // (|x|<1)**+-inf = 0,inf
|
|
281
|
+
if (hy >= 0n) output = 0.0W else output = y * -1.0W
|
|
282
|
+
}
|
|
283
|
+
} else if (iy == 0x3FF00000n) {
|
|
284
|
+
foundOutput = true
|
|
285
|
+
if (hy >= 0n) output = x else output = 1.0W / x
|
|
286
|
+
} else if (hy == 0x3FE00000n) {
|
|
287
|
+
foundOutput = true
|
|
288
|
+
output = x * x
|
|
289
|
+
} else if (hy == 0x3FE00000n) {
|
|
290
|
+
if (hx >= 0n) {
|
|
291
|
+
foundOutput = true
|
|
292
|
+
output = WasmF64.sqrt(x)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (foundOutput) {
|
|
297
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
298
|
+
} else {
|
|
299
|
+
let mut ax = WasmF64.abs(x)
|
|
300
|
+
let mut z = 0.0W
|
|
301
|
+
if (
|
|
302
|
+
lx == 0n && (ix == 0n || ix == 0x7FF00000n || ix == 0x3FF00000n)
|
|
303
|
+
) {
|
|
304
|
+
z = ax
|
|
305
|
+
if (hy < 0n) z = 1.0W / z
|
|
306
|
+
if (hx < 0n) {
|
|
307
|
+
if ((ix - 0x3FF00000n | yisint) == 0n) {
|
|
308
|
+
let d = WasmF64.sub(z, z)
|
|
309
|
+
z = d / d
|
|
310
|
+
} else if (yisint == 1n) z *= -1.0W
|
|
311
|
+
}
|
|
312
|
+
WasmI32.toGrain(newFloat64(z)): Number
|
|
313
|
+
} else {
|
|
314
|
+
let mut s = 1.0W
|
|
315
|
+
if (hx < 0n) {
|
|
316
|
+
if (yisint == 0n) {
|
|
317
|
+
let d = WasmF64.sub(x, x)
|
|
318
|
+
foundOutput = true
|
|
319
|
+
output = d / d
|
|
320
|
+
} else if (yisint == 1n) s = -1.0W
|
|
321
|
+
}
|
|
322
|
+
if (foundOutput) {
|
|
323
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
324
|
+
} else {
|
|
325
|
+
let mut t1 = 0.0W,
|
|
326
|
+
t2 = 0.0W,
|
|
327
|
+
p_h = 0.0W,
|
|
328
|
+
p_l = 0.0W,
|
|
329
|
+
r = 0.0W,
|
|
330
|
+
t = 0.0W,
|
|
331
|
+
u = 0.0W,
|
|
332
|
+
v = 0.0W,
|
|
333
|
+
w = 0.0W
|
|
334
|
+
let mut j = 0n, n = 0n
|
|
335
|
+
if (iy > 0x41E00000n) {
|
|
336
|
+
if (iy > 0x43F00000n) {
|
|
337
|
+
if (ix <= 0x3FEFFFFFn) {
|
|
338
|
+
foundOutput = true
|
|
339
|
+
if (hy < 0n) output = huge * huge else output = tiny * tiny
|
|
340
|
+
} else if (ix >= 0x3FF00000n) {
|
|
341
|
+
foundOutput = true
|
|
342
|
+
if (hy > 0n) output = huge * huge else output = tiny * tiny
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (!foundOutput) {
|
|
346
|
+
if (ix < 0x3FEFFFFFn) {
|
|
347
|
+
foundOutput = true
|
|
348
|
+
if (hy < 0n) {
|
|
349
|
+
output = s * huge * huge
|
|
350
|
+
} else {
|
|
351
|
+
output = s * tiny * tiny
|
|
352
|
+
}
|
|
353
|
+
} else if (ix > 0x3FF00000n) {
|
|
354
|
+
foundOutput = true
|
|
355
|
+
if (hy > 0n) {
|
|
356
|
+
output = s * huge * huge
|
|
357
|
+
} else {
|
|
358
|
+
output = s * tiny * tiny
|
|
359
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
let (-) = WasmF64.sub
|
|
362
|
+
let (&) = WasmI64.and
|
|
363
|
+
t = ax - 1.0W
|
|
364
|
+
w = t * t * (0.5W - t * (inv3 - t * 0.25W))
|
|
365
|
+
u = ivln2_h * t
|
|
366
|
+
v = t * ivln2_l - w * ivln2
|
|
367
|
+
t1 = WasmF64.add(u, v)
|
|
368
|
+
t1 = WasmF64.reinterpretI64(
|
|
369
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
370
|
+
)
|
|
371
|
+
t2 = v - (t1 - u)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
let mut ss = 0.0W,
|
|
376
|
+
s2 = 0.0W,
|
|
377
|
+
s_h = 0.0W,
|
|
378
|
+
s_l = 0.0W,
|
|
379
|
+
t_h = 0.0W,
|
|
380
|
+
t_l = 0.0W
|
|
381
|
+
n = 0n
|
|
382
|
+
if (ix < 0x00100000n) {
|
|
383
|
+
let (>>) = WasmI64.shrU
|
|
384
|
+
ax *= two53
|
|
385
|
+
n -= 53n
|
|
386
|
+
ix = WasmI32.wrapI64(WasmI64.reinterpretF64(ax) >> 32N)
|
|
387
|
+
}
|
|
388
|
+
n += (ix >> 20n) - 0x3FFn
|
|
389
|
+
j = ix & 0x000FFFFFn
|
|
390
|
+
ix = j | 0x3FF00000n
|
|
391
|
+
if (j <= 0x3988En) {
|
|
392
|
+
k = 0n
|
|
393
|
+
} else if (j < 0xBB67An) {
|
|
394
|
+
k = 1n
|
|
395
|
+
} else {
|
|
396
|
+
k = 0n
|
|
397
|
+
n += 1n
|
|
398
|
+
ix -= 0x00100000n
|
|
399
|
+
}
|
|
400
|
+
let (&) = WasmI64.and
|
|
401
|
+
let (|) = WasmI64.or
|
|
402
|
+
let (<<) = WasmI64.shl
|
|
403
|
+
ax = WasmF64.reinterpretI64(
|
|
404
|
+
WasmI64.reinterpretF64(ax) & 0xFFFFFFFFN |
|
|
405
|
+
WasmI64.extendI32S(ix) << 32N
|
|
406
|
+
)
|
|
407
|
+
let bp = if (k != 0n) 1.5W else 1.0W
|
|
408
|
+
u = WasmF64.sub(ax, bp)
|
|
409
|
+
v = 1.0W / WasmF64.add(ax, bp)
|
|
410
|
+
ss = u * v
|
|
411
|
+
s_h = ss
|
|
412
|
+
s_h = WasmF64.reinterpretI64(
|
|
413
|
+
WasmI64.reinterpretF64(s_h) & 0xFFFFFFFF00000000N
|
|
414
|
+
)
|
|
415
|
+
t_h = WasmF64.reinterpretI64(
|
|
416
|
+
WasmI64.shl(
|
|
417
|
+
WasmI64.extendI32S(
|
|
418
|
+
WasmI32.or(WasmI32.shrS(ix, 1n), 0x20000000n) +
|
|
419
|
+
0x00080000n +
|
|
420
|
+
WasmI32.shl(k, 18n)
|
|
421
|
+
),
|
|
422
|
+
32N
|
|
423
|
+
)
|
|
424
|
+
)
|
|
425
|
+
let (-) = WasmF64.sub
|
|
426
|
+
let (+) = WasmF64.add
|
|
427
|
+
t_l = ax - (t_h - bp)
|
|
428
|
+
s_l = v * (u - s_h * t_h - s_h * t_l)
|
|
429
|
+
s2 = ss * ss
|
|
430
|
+
//formatter-ignore
|
|
431
|
+
r = s2 * s2 * (l1 + s2 * (l2 + s2 * (l3 + s2 * (l4 + s2 * (l5 + s2 * l6)))))
|
|
432
|
+
r += s_l * (s_h + ss)
|
|
433
|
+
s2 = s_h * s_h
|
|
434
|
+
t_h = 3.0W + s2 + r
|
|
435
|
+
t_h = WasmF64.reinterpretI64(
|
|
436
|
+
WasmI64.reinterpretF64(t_h) & 0xFFFFFFFF00000000N
|
|
437
|
+
)
|
|
438
|
+
t_l = r - (t_h - 3.0W - s2)
|
|
439
|
+
u = s_h * t_h
|
|
440
|
+
v = s_l * t_h + t_l * ss
|
|
441
|
+
p_h = u + v
|
|
442
|
+
p_h = WasmF64.reinterpretI64(
|
|
443
|
+
WasmI64.reinterpretF64(p_h) & 0xFFFFFFFF00000000N
|
|
444
|
+
)
|
|
445
|
+
p_l = v - (p_h - u)
|
|
446
|
+
let z_h = cp_h * p_h
|
|
447
|
+
let dp_l = if (k != 0n) dp_l1 else 0.0W
|
|
448
|
+
let z_l = cp_l * p_h + p_l * cp + dp_l
|
|
449
|
+
t = WasmF64.convertI32S(n)
|
|
450
|
+
let dp_h = if (k != 0n) dp_h1 else 0.0W
|
|
451
|
+
t1 = z_h + z_l + dp_h + t
|
|
452
|
+
t1 = WasmF64.reinterpretI64(
|
|
453
|
+
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
454
|
+
)
|
|
455
|
+
t2 = z_l - (t1 - t - dp_h - z_h)
|
|
456
|
+
}
|
|
457
|
+
if (foundOutput) {
|
|
458
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
459
|
+
} else {
|
|
460
|
+
let (>) = WasmF64.gt
|
|
461
|
+
let (&) = WasmI64.and
|
|
462
|
+
let (-) = WasmF64.sub
|
|
463
|
+
let (+) = WasmF64.add
|
|
464
|
+
let (>>) = WasmI64.shrS
|
|
465
|
+
let y1 = WasmF64.reinterpretI64(
|
|
466
|
+
WasmI64.reinterpretF64(y) & 0xFFFFFFFF00000000N
|
|
467
|
+
)
|
|
468
|
+
p_l = (y - y1) * t1 + y * t2
|
|
469
|
+
p_h = y1 * t1
|
|
470
|
+
z = p_l + p_h
|
|
471
|
+
let u_ = WasmI64.reinterpretF64(z)
|
|
472
|
+
let j = WasmI32.wrapI64(u_ >> 32N)
|
|
473
|
+
let i = WasmI32.wrapI64(u_)
|
|
474
|
+
if (j >= 0x40900000n) {
|
|
475
|
+
if ((WasmI32.sub(j, 0x40900000n) | i) != 0n) {
|
|
476
|
+
foundOutput = true
|
|
477
|
+
output = s * huge * huge
|
|
478
|
+
} else if (p_l + ovt > z - p_h) {
|
|
479
|
+
foundOutput = true
|
|
480
|
+
output = s * huge * huge
|
|
481
|
+
}
|
|
482
|
+
} else if (WasmI32.and(j, 0x7FFFFFFFn) >= 0x4090CC00n) {
|
|
483
|
+
if (WasmI32.sub(j, 0xC090CC00n | i) != 0n) {
|
|
484
|
+
foundOutput = true
|
|
485
|
+
output = s * tiny * tiny
|
|
486
|
+
} else if (WasmF64.le(p_l, z - p_h)) {
|
|
487
|
+
foundOutput = true
|
|
488
|
+
output = s * tiny * tiny
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (foundOutput) {
|
|
492
|
+
WasmI32.toGrain(newFloat64(output)): Number
|
|
493
|
+
} else {
|
|
494
|
+
let (&) = WasmI32.and
|
|
495
|
+
let (>>) = WasmI32.shrS
|
|
496
|
+
let (-) = WasmI32.sub
|
|
497
|
+
let (+) = WasmI32.add
|
|
498
|
+
let (>) = WasmI32.gtS
|
|
499
|
+
let (*) = WasmI32.mul
|
|
500
|
+
let i = j & 0x7FFFFFFFn
|
|
501
|
+
k = (i >> 20n) - 0x3FFn
|
|
502
|
+
n = 0n
|
|
503
|
+
if (i > 0x3FE00000n) {
|
|
504
|
+
n = j + (0x00100000n >> k + 1n)
|
|
505
|
+
k = ((n & 0x7FFFFFFFn) >> 20n) - 0x3FFn
|
|
506
|
+
t = 0.0W
|
|
507
|
+
t = WasmF64.reinterpretI64(
|
|
508
|
+
WasmI64.shl(
|
|
509
|
+
WasmI64.extendI32S(
|
|
510
|
+
n & WasmI32.xor(0x000FFFFFn >> k, -1n)
|
|
511
|
+
),
|
|
512
|
+
32N
|
|
513
|
+
)
|
|
514
|
+
)
|
|
515
|
+
n = (n & 0x000FFFFFn | 0x00100000n) >> 20n - k
|
|
516
|
+
if (j < 0n) n *= -1n
|
|
517
|
+
p_h = WasmF64.sub(p_h, t)
|
|
518
|
+
}
|
|
519
|
+
let (&) = WasmI64.and
|
|
520
|
+
let (|) = WasmI64.or
|
|
521
|
+
let (*) = WasmF64.mul
|
|
522
|
+
let (-) = WasmF64.sub
|
|
523
|
+
let (+) = WasmF64.add
|
|
524
|
+
t = WasmF64.add(p_l, p_h)
|
|
525
|
+
t = WasmF64.reinterpretI64(
|
|
526
|
+
WasmI64.reinterpretF64(t) & 0xFFFFFFFF00000000N
|
|
527
|
+
)
|
|
528
|
+
u = t * lg2_h
|
|
529
|
+
v = (p_l - (t - p_h)) * lg2 + t * lg2_l
|
|
530
|
+
z = u + v
|
|
531
|
+
w = v - (z - u)
|
|
532
|
+
t = z * z
|
|
533
|
+
t1 = z - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5))))
|
|
534
|
+
r = z * t1 / (t1 - 2.0W) - (w + z * w)
|
|
535
|
+
z = 1.0W - (r - z)
|
|
536
|
+
let j = WasmI32.add(
|
|
537
|
+
WasmI32.wrapI64(
|
|
538
|
+
WasmI64.shrS(WasmI64.reinterpretF64(z), 32N)
|
|
539
|
+
),
|
|
540
|
+
WasmI32.shl(n, 20n)
|
|
541
|
+
)
|
|
542
|
+
if (WasmI32.shrS(j, 20n) <= 0n) {
|
|
543
|
+
z = scalbn(z, n)
|
|
544
|
+
} else {
|
|
545
|
+
z = WasmF64.reinterpretI64(
|
|
546
|
+
WasmI64.reinterpretF64(z) & 0xFFFFFFFFN |
|
|
547
|
+
WasmI64.shl(WasmI64.extendI32S(j), 32N)
|
|
548
|
+
)
|
|
549
|
+
}
|
|
550
|
+
WasmI32.toGrain(newFloat64(s * z)): Number
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Computes the exponentiation of Euler's number to the given power.
|
|
563
|
+
*
|
|
564
|
+
* @param power: The exponent number
|
|
565
|
+
* @returns The `Number.e` value raised to the given power
|
|
566
|
+
*
|
|
567
|
+
* @since v0.5.4
|
|
568
|
+
*/
|
|
569
|
+
export let exp = power => {
|
|
570
|
+
if (power == 0) 1 else pow(e, power)
|
|
571
|
+
}
|
|
97
572
|
/**
|
|
98
573
|
* Computes the square root of its operand.
|
|
99
574
|
*
|
|
@@ -140,8 +615,9 @@ export let sign = x => {
|
|
|
140
615
|
* @returns The smaller of the two operands
|
|
141
616
|
*
|
|
142
617
|
* @since v0.4.0
|
|
618
|
+
* @history v0.5.4: Handle NaN properly
|
|
143
619
|
*/
|
|
144
|
-
export let min = (x: Number, y: Number) => if (y
|
|
620
|
+
export let min = (x: Number, y: Number) => if (compare(x, y) < 0) x else y
|
|
145
621
|
|
|
146
622
|
/**
|
|
147
623
|
* Returns the larger of its operands.
|
|
@@ -151,8 +627,9 @@ export let min = (x: Number, y: Number) => if (y > x) x else y
|
|
|
151
627
|
* @returns The larger of the two operands
|
|
152
628
|
*
|
|
153
629
|
* @since v0.4.0
|
|
630
|
+
* @history v0.5.4: Handle NaN properly
|
|
154
631
|
*/
|
|
155
|
-
export let max = (x: Number, y: Number) => if (x >
|
|
632
|
+
export let max = (x: Number, y: Number) => if (compare(x, y) > 0) x else y
|
|
156
633
|
|
|
157
634
|
/**
|
|
158
635
|
* Rounds its operand up to the next largest integer.
|
|
@@ -161,12 +638,19 @@ export let max = (x: Number, y: Number) => if (x > y) x else y
|
|
|
161
638
|
* @returns The next largest integer of the operand
|
|
162
639
|
*
|
|
163
640
|
* @since v0.4.0
|
|
641
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
164
642
|
*/
|
|
165
643
|
@unsafe
|
|
166
644
|
export let ceil = (x: Number) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
645
|
+
if (x != x) {
|
|
646
|
+
nan
|
|
647
|
+
} else if (x == infinity) {
|
|
648
|
+
infinity
|
|
649
|
+
} else {
|
|
650
|
+
let xval = coerceNumberToWasmF64(x)
|
|
651
|
+
let ceiling = WasmI64.truncF64S(WasmF64.ceil(xval))
|
|
652
|
+
WasmI32.toGrain(reducedInteger(ceiling)): Number
|
|
653
|
+
}
|
|
170
654
|
}
|
|
171
655
|
|
|
172
656
|
/**
|
|
@@ -176,12 +660,19 @@ export let ceil = (x: Number) => {
|
|
|
176
660
|
* @returns The previous integer of the operand
|
|
177
661
|
*
|
|
178
662
|
* @since v0.4.0
|
|
663
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
179
664
|
*/
|
|
180
665
|
@unsafe
|
|
181
666
|
export let floor = (x: Number) => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
667
|
+
if (x != x) {
|
|
668
|
+
nan
|
|
669
|
+
} else if (x == infinity) {
|
|
670
|
+
infinity
|
|
671
|
+
} else {
|
|
672
|
+
let xval = coerceNumberToWasmF64(x)
|
|
673
|
+
let floored = WasmI64.truncF64S(WasmF64.floor(xval))
|
|
674
|
+
WasmI32.toGrain(reducedInteger(floored)): Number
|
|
675
|
+
}
|
|
185
676
|
}
|
|
186
677
|
|
|
187
678
|
/**
|
|
@@ -191,12 +682,19 @@ export let floor = (x: Number) => {
|
|
|
191
682
|
* @returns The integer part of the operand
|
|
192
683
|
*
|
|
193
684
|
* @since v0.4.0
|
|
685
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
194
686
|
*/
|
|
195
687
|
@unsafe
|
|
196
688
|
export let trunc = (x: Number) => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
689
|
+
if (x != x) {
|
|
690
|
+
nan
|
|
691
|
+
} else if (x == infinity) {
|
|
692
|
+
infinity
|
|
693
|
+
} else {
|
|
694
|
+
let xval = coerceNumberToWasmF64(x)
|
|
695
|
+
let trunced = WasmI64.truncF64S(xval)
|
|
696
|
+
WasmI32.toGrain(reducedInteger(trunced)): Number
|
|
697
|
+
}
|
|
200
698
|
}
|
|
201
699
|
|
|
202
700
|
/**
|
|
@@ -206,12 +704,19 @@ export let trunc = (x: Number) => {
|
|
|
206
704
|
* @returns The nearest integer to the operand
|
|
207
705
|
*
|
|
208
706
|
* @since v0.4.0
|
|
707
|
+
* @history v0.5.4: Handle NaN and Infinity properly
|
|
209
708
|
*/
|
|
210
709
|
@unsafe
|
|
211
710
|
export let round = (x: Number) => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
711
|
+
if (x != x) {
|
|
712
|
+
nan
|
|
713
|
+
} else if (x == infinity) {
|
|
714
|
+
infinity
|
|
715
|
+
} else {
|
|
716
|
+
let xval = coerceNumberToWasmF64(x)
|
|
717
|
+
let rounded = WasmI64.truncF64S(WasmF64.nearest(xval))
|
|
718
|
+
WasmI32.toGrain(reducedInteger(rounded)): Number
|
|
719
|
+
}
|
|
215
720
|
}
|
|
216
721
|
|
|
217
722
|
/**
|
|
@@ -386,7 +891,80 @@ export let isInfinite = (x: Number) => {
|
|
|
386
891
|
*
|
|
387
892
|
* @since v0.4.5
|
|
388
893
|
*/
|
|
389
|
-
export parseInt
|
|
894
|
+
export let parseInt = Atoi.parseInt
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Parses a string representation of a float into a `Number`. Underscores that appear
|
|
898
|
+
* in numeric portions of the input are ignored.
|
|
899
|
+
*
|
|
900
|
+
* @param input: The string to parse
|
|
901
|
+
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
|
|
902
|
+
*
|
|
903
|
+
* @since v0.5.5
|
|
904
|
+
*/
|
|
905
|
+
export let parseFloat = Atof.parseFloat
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Parses a string representation of an integer, float, or rational into a `Number`.
|
|
909
|
+
* Underscores that appear in the numeric portion of the input are ignored.
|
|
910
|
+
*
|
|
911
|
+
* @param input: The string to parse
|
|
912
|
+
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
|
|
913
|
+
*
|
|
914
|
+
* @since v0.5.5
|
|
915
|
+
*/
|
|
916
|
+
@unsafe
|
|
917
|
+
export let parse = input => {
|
|
918
|
+
match (parseInt(input, 10)) {
|
|
919
|
+
Ok(number) => Ok(number),
|
|
920
|
+
Err(msg) =>
|
|
921
|
+
match (parseFloat(input)) {
|
|
922
|
+
Ok(number) => Ok(number),
|
|
923
|
+
Err(_) => {
|
|
924
|
+
// Split the input on a `/` and attempt to parse a rational
|
|
925
|
+
let (+) = WasmI32.add
|
|
926
|
+
let (-) = WasmI32.sub
|
|
927
|
+
let (<) = WasmI32.ltU
|
|
928
|
+
let (==) = WasmI32.eq
|
|
929
|
+
|
|
930
|
+
// Search for `/`
|
|
931
|
+
let input = WasmI32.fromGrain(input)
|
|
932
|
+
let len = WasmI32.load(input, 4n)
|
|
933
|
+
let mut slashIdx = -1n
|
|
934
|
+
for (let mut i = 0n; i < len; i += 1n) {
|
|
935
|
+
if (WasmI32.load8U(input + i, 8n) == 0x2fn) {
|
|
936
|
+
slashIdx = i
|
|
937
|
+
break
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
if (slashIdx == -1n) {
|
|
942
|
+
Err(msg)
|
|
943
|
+
} else {
|
|
944
|
+
let numeratorLen = slashIdx
|
|
945
|
+
let denominatorLen = len - slashIdx - 1n
|
|
946
|
+
|
|
947
|
+
let numerator = allocateString(numeratorLen)
|
|
948
|
+
Memory.copy(numerator + 8n, input + 8n, numeratorLen)
|
|
949
|
+
let numerator = WasmI32.toGrain(numerator): String
|
|
950
|
+
|
|
951
|
+
let denominator = allocateString(denominatorLen)
|
|
952
|
+
Memory.copy(
|
|
953
|
+
denominator + 8n,
|
|
954
|
+
input + 8n + slashIdx + 1n,
|
|
955
|
+
denominatorLen
|
|
956
|
+
)
|
|
957
|
+
let denominator = WasmI32.toGrain(denominator): String
|
|
958
|
+
|
|
959
|
+
match ((parseInt(numerator, 10), parseInt(denominator, 10))) {
|
|
960
|
+
(Ok(numerator), Ok(denominator)) => Ok(numerator / denominator),
|
|
961
|
+
(Err(msg), _) | (_, Err(msg)) => Err(msg),
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
},
|
|
965
|
+
},
|
|
966
|
+
}
|
|
967
|
+
}
|
|
390
968
|
|
|
391
969
|
/**
|
|
392
970
|
* Computes how many times pi has to be subtracted to achieve the required bounds for sin.
|
|
@@ -417,14 +995,19 @@ let chebyshevSine = (radians: Number) => {
|
|
|
417
995
|
* @returns The computed sine
|
|
418
996
|
*
|
|
419
997
|
* @since v0.5.2
|
|
998
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
420
999
|
*/
|
|
421
1000
|
export let sin = (radians: Number) => {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (quot % 2 == 0) {
|
|
425
|
-
chebyshevSine(bounded)
|
|
1001
|
+
if (radians != radians || radians == infinity) {
|
|
1002
|
+
nan
|
|
426
1003
|
} else {
|
|
427
|
-
|
|
1004
|
+
let quot = reduceToPiBound(radians)
|
|
1005
|
+
let bounded = radians - pi * quot
|
|
1006
|
+
if (quot % 2 == 0) {
|
|
1007
|
+
chebyshevSine(bounded)
|
|
1008
|
+
} else {
|
|
1009
|
+
neg(chebyshevSine(bounded))
|
|
1010
|
+
}
|
|
428
1011
|
}
|
|
429
1012
|
}
|
|
430
1013
|
|
|
@@ -435,7 +1018,125 @@ export let sin = (radians: Number) => {
|
|
|
435
1018
|
* @returns The computed cosine
|
|
436
1019
|
*
|
|
437
1020
|
* @since v0.5.2
|
|
1021
|
+
* @history v0.5.4: Handle NaN and Infinity
|
|
438
1022
|
*/
|
|
439
1023
|
export let cos = (radians: Number) => {
|
|
440
|
-
|
|
1024
|
+
if (radians != radians || radians == infinity) {
|
|
1025
|
+
nan
|
|
1026
|
+
} else {
|
|
1027
|
+
sin(pi / 2 + radians)
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Computes the tangent of a number (in radians) using Chebyshev polynomials.
|
|
1033
|
+
*
|
|
1034
|
+
* @param radians: The input in radians
|
|
1035
|
+
* @returns The computed tangent
|
|
1036
|
+
*
|
|
1037
|
+
* @since v0.5.4
|
|
1038
|
+
*/
|
|
1039
|
+
export let tan = (radians: Number) => {
|
|
1040
|
+
if (isNaN(radians) || isInfinite(radians)) {
|
|
1041
|
+
nan
|
|
1042
|
+
} else {
|
|
1043
|
+
sin(radians) / cos(radians)
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// Math.gamma implemented using the Lanczos approximation
|
|
1048
|
+
// https://en.wikipedia.org/wiki/Lanczos_approximation
|
|
1049
|
+
/**
|
|
1050
|
+
* Computes the gamma function of a value using Lanczos approximation.
|
|
1051
|
+
*
|
|
1052
|
+
* @param z: The value to interpolate
|
|
1053
|
+
* @returns The gamma of the given value
|
|
1054
|
+
*
|
|
1055
|
+
* @throws InvalidArgument(String): When `z` is zero
|
|
1056
|
+
*
|
|
1057
|
+
* @since v0.5.4
|
|
1058
|
+
*/
|
|
1059
|
+
export let rec gamma = z => {
|
|
1060
|
+
if (z == 0) {
|
|
1061
|
+
throw Exception.InvalidArgument("Gamma of 0 is undefined")
|
|
1062
|
+
} else if (isInteger(z) && z > 0) {
|
|
1063
|
+
let mut output = 1
|
|
1064
|
+
for (let mut i = 1; i < z; i += 1) {
|
|
1065
|
+
output *= i
|
|
1066
|
+
}
|
|
1067
|
+
output
|
|
1068
|
+
} else {
|
|
1069
|
+
let mut z = z
|
|
1070
|
+
let g = 7
|
|
1071
|
+
let c = [>
|
|
1072
|
+
0.99999999999980993,
|
|
1073
|
+
676.5203681218851,
|
|
1074
|
+
-1259.1392167224028,
|
|
1075
|
+
771.32342877765313,
|
|
1076
|
+
-176.61502916214059,
|
|
1077
|
+
12.507343278686905,
|
|
1078
|
+
-0.13857109526572012,
|
|
1079
|
+
9.9843695780195716e-6,
|
|
1080
|
+
1.5056327351493116e-7,
|
|
1081
|
+
]
|
|
1082
|
+
let mut output = 0
|
|
1083
|
+
if (z < 0.5) {
|
|
1084
|
+
output = pi / (sin(pi * z) * gamma(1 - z))
|
|
1085
|
+
} else if (z == 0.5) {
|
|
1086
|
+
// Handle this case separately because it is out of the domain of Number.pow when calculating
|
|
1087
|
+
output = 1.7724538509055159
|
|
1088
|
+
} else {
|
|
1089
|
+
z -= 1
|
|
1090
|
+
let mut x = c[0]
|
|
1091
|
+
for (let mut i = 1; i < g + 2; i += 1) {
|
|
1092
|
+
x += c[i] / (z + i)
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
let t = z + g + 0.5
|
|
1096
|
+
output = sqrt(2 * pi) * pow(t, z + 0.5) * exp(t * -1) * x
|
|
1097
|
+
}
|
|
1098
|
+
if (abs(output) == infinity) infinity else output
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Computes the product of consecutive integers for an integer input and computes the gamma function for non-integer inputs.
|
|
1104
|
+
*
|
|
1105
|
+
* @param n: The value to factorialize
|
|
1106
|
+
* @returns The factorial of the given value
|
|
1107
|
+
*
|
|
1108
|
+
* @throws InvalidArgument(String): When `n` is negative
|
|
1109
|
+
*
|
|
1110
|
+
* @since v0.5.4
|
|
1111
|
+
*/
|
|
1112
|
+
export let rec factorial = n => {
|
|
1113
|
+
if (isInteger(n) && n < 0) gamma(abs(n) + 1) * -1 else if (
|
|
1114
|
+
!isInteger(n) && n < 0
|
|
1115
|
+
) {
|
|
1116
|
+
throw Exception.InvalidArgument(
|
|
1117
|
+
"Cannot compute the factorial of a negative non-integer"
|
|
1118
|
+
)
|
|
1119
|
+
} else {
|
|
1120
|
+
gamma(n + 1)
|
|
1121
|
+
}
|
|
441
1122
|
}
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* Converts degrees to radians.
|
|
1126
|
+
*
|
|
1127
|
+
* @param degrees: The value to convert
|
|
1128
|
+
* @returns The value in radians
|
|
1129
|
+
*
|
|
1130
|
+
* @since v0.5.4
|
|
1131
|
+
*/
|
|
1132
|
+
export let toRadians = degrees => degrees * (pi / 180)
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Converts radians to degrees.
|
|
1136
|
+
*
|
|
1137
|
+
* @param radians: The value to convert
|
|
1138
|
+
* @returns The value in degrees
|
|
1139
|
+
*
|
|
1140
|
+
* @since v0.5.4
|
|
1141
|
+
*/
|
|
1142
|
+
export let toDegrees = radians => radians * (180 / pi)
|