@typeonce/ritmo-math 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +14 -4
  3. package/dist/Collide2.d.ts +2 -1
  4. package/dist/Collide2.d.ts.map +1 -1
  5. package/dist/Collide2.js +10 -6
  6. package/dist/Collide2.js.map +1 -1
  7. package/dist/FlowField.d.ts.map +1 -1
  8. package/dist/FlowField.js +2 -1
  9. package/dist/FlowField.js.map +1 -1
  10. package/dist/InputAxis.js +1 -1
  11. package/dist/Ops.d.ts +209 -0
  12. package/dist/Ops.d.ts.map +1 -0
  13. package/dist/Ops.js +210 -0
  14. package/dist/Ops.js.map +1 -0
  15. package/dist/Random.d.ts +63 -10
  16. package/dist/Random.d.ts.map +1 -1
  17. package/dist/Random.js +57 -32
  18. package/dist/Random.js.map +1 -1
  19. package/dist/Scalar.d.ts +7 -2
  20. package/dist/Scalar.d.ts.map +1 -1
  21. package/dist/Scalar.js +2 -1
  22. package/dist/Scalar.js.map +1 -1
  23. package/dist/SpatialGrid.d.ts +7 -2
  24. package/dist/SpatialGrid.d.ts.map +1 -1
  25. package/dist/SpatialGrid.js +35 -4
  26. package/dist/SpatialGrid.js.map +1 -1
  27. package/dist/Vec2.d.ts.map +1 -1
  28. package/dist/Vec2.js +8 -7
  29. package/dist/Vec2.js.map +1 -1
  30. package/dist/Vector2.d.ts +12 -0
  31. package/dist/Vector2.d.ts.map +1 -1
  32. package/dist/Vector2.js +12 -0
  33. package/dist/Vector2.js.map +1 -1
  34. package/dist/index.d.ts +5 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +5 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/internal/fdlibm.d.ts +43 -0
  39. package/dist/internal/fdlibm.d.ts.map +1 -0
  40. package/dist/internal/fdlibm.js +1291 -0
  41. package/dist/internal/fdlibm.js.map +1 -0
  42. package/dist/internal/vector2.d.ts.map +1 -1
  43. package/dist/internal/vector2.js +2 -1
  44. package/dist/internal/vector2.js.map +1 -1
  45. package/package.json +3 -2
  46. package/src/Collide2.ts +10 -6
  47. package/src/FlowField.ts +2 -1
  48. package/src/InputAxis.ts +1 -1
  49. package/src/Ops.ts +232 -0
  50. package/src/Random.ts +104 -16
  51. package/src/Scalar.ts +7 -2
  52. package/src/SpatialGrid.ts +40 -6
  53. package/src/Vec2.ts +9 -7
  54. package/src/Vector2.ts +12 -0
  55. package/src/index.ts +5 -0
  56. package/src/internal/fdlibm.ts +1256 -0
  57. package/src/internal/vector2.ts +2 -1
@@ -0,0 +1,1256 @@
1
+ /**
2
+ * Pure-JavaScript ports of FreeBSD msun / musl libm (originally Sun fdlibm),
3
+ * built only from `+ - * /`, `Math.sqrt`, and bit access. ECMAScript rounds
4
+ * each of those exactly, so every engine and CPU returns the same bits.
5
+ *
6
+ * Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
7
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
8
+ * Permission to use, copy, modify, and distribute this software is freely
9
+ * granted, provided that this notice is preserved.
10
+ *
11
+ * musl libm is MIT licensed, Copyright (c) 2005-2020 Rich Felker, et al.
12
+ *
13
+ * Changes from the C sources: results follow ECMAScript where it differs from
14
+ * C (`pow(1, NaN)` and `pow(±1, ±Infinity)` are NaN), arguments of sin,
15
+ * cos, and tan beyond 2^20·π/2 are reduced exactly with BigInt instead of
16
+ * `__rem_pio2_large`, and `exp(1)` returns `Math.E`.
17
+ *
18
+ * @internal
19
+ */
20
+
21
+ const scratch = new Float64Array(1)
22
+ const words = new Uint32Array(scratch.buffer)
23
+ const LITTLE_ENDIAN = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1
24
+ const HI = LITTLE_ENDIAN ? 1 : 0
25
+ const LO = LITTLE_ENDIAN ? 0 : 1
26
+
27
+ /** The high 32 bits of `x`, as a signed integer (sign, exponent, top of the mantissa). */
28
+ const highWord = (x: number): number => {
29
+ scratch[0] = x
30
+ return words[HI]! | 0
31
+ }
32
+
33
+ /** The low 32 bits of `x`, unsigned. */
34
+ const lowWord = (x: number): number => {
35
+ scratch[0] = x
36
+ return words[LO]!
37
+ }
38
+
39
+ const fromWords = (high: number, low: number): number => {
40
+ words[HI] = high
41
+ words[LO] = low
42
+ return scratch[0]!
43
+ }
44
+
45
+ /** `x` with its low 32 bits cleared. */
46
+ const clearLow = (x: number): number => {
47
+ scratch[0] = x
48
+ words[LO] = 0
49
+ return scratch[0]!
50
+ }
51
+
52
+ const TWO_1023 = fromWords(0x7fe00000, 0)
53
+ const TWO_M1022 = fromWords(0x00100000, 0)
54
+ const TWO_53 = 9007199254740992
55
+
56
+ /** `x * 2^n`, rounded once. */
57
+ const scalbn = (x: number, n: number): number => {
58
+ let y = x
59
+ let k = n
60
+ if (k > 1023) {
61
+ y *= TWO_1023
62
+ k -= 1023
63
+ if (k > 1023) {
64
+ y *= TWO_1023
65
+ k -= 1023
66
+ if (k > 1023) k = 1023
67
+ }
68
+ } else if (k < -1022) {
69
+ // Keep the final k below -53 to avoid double rounding into subnormals.
70
+ y *= TWO_M1022 * TWO_53
71
+ k += 1022 - 53
72
+ if (k < -1022) {
73
+ y *= TWO_M1022 * TWO_53
74
+ k += 1022 - 53
75
+ if (k < -1022) k = -1022
76
+ }
77
+ }
78
+ return y * fromWords((0x3ff + k) << 20, 0)
79
+ }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Argument reduction: x = n·(π/2) + (y0 + y1), |y0 + y1| <= π/4
83
+
84
+ let reducedHigh = 0
85
+ let reducedLow = 0
86
+
87
+ const TO_INT = 1.5 / 2.220446049250313e-16
88
+ const PIO4 = 7.85398163397448278999e-01
89
+ const INVPIO2 = 6.36619772367581382433e-01
90
+ const PIO2_1 = 1.57079632673412561417e+00
91
+ const PIO2_1T = 6.07710050650619224932e-11
92
+ const PIO2_2 = 6.07710050630396597660e-11
93
+ const PIO2_2T = 2.02226624879595063154e-21
94
+ const PIO2_3 = 2.02226624871116645580e-21
95
+ const PIO2_3T = 8.47842766036889956997e-32
96
+
97
+ /** Sets `reducedHigh`/`reducedLow` and returns n (only n mod 4 is meaningful for huge x). */
98
+ const remPio2 = (x: number): number => {
99
+ const ix = highWord(x) & 0x7fffffff
100
+ if (ix < 0x413921fb) {
101
+ // |x| < 2^20·π/2: Cody–Waite reduction with up to three rounds.
102
+ let fn = x * INVPIO2 + TO_INT - TO_INT
103
+ let n = fn | 0
104
+ let r = x - fn * PIO2_1
105
+ let w = fn * PIO2_1T
106
+ if (r - w < -PIO4) {
107
+ n--
108
+ fn--
109
+ r = x - fn * PIO2_1
110
+ w = fn * PIO2_1T
111
+ } else if (r - w > PIO4) {
112
+ n++
113
+ fn++
114
+ r = x - fn * PIO2_1
115
+ w = fn * PIO2_1T
116
+ }
117
+ let y0 = r - w
118
+ const ex = ix >> 20
119
+ let ey = (highWord(y0) >> 20) & 0x7ff
120
+ if (ex - ey > 16) {
121
+ let t = r
122
+ w = fn * PIO2_2
123
+ r = t - w
124
+ w = fn * PIO2_2T - ((t - r) - w)
125
+ y0 = r - w
126
+ ey = (highWord(y0) >> 20) & 0x7ff
127
+ if (ex - ey > 49) {
128
+ t = r
129
+ w = fn * PIO2_3
130
+ r = t - w
131
+ w = fn * PIO2_3T - ((t - r) - w)
132
+ y0 = r - w
133
+ }
134
+ }
135
+ reducedHigh = y0
136
+ reducedLow = (r - y0) - w
137
+ return n
138
+ }
139
+ if (ix >= 0x7ff00000) {
140
+ reducedHigh = x - x
141
+ reducedLow = reducedHigh
142
+ return 0
143
+ }
144
+ return remPio2Large(x)
145
+ }
146
+
147
+ // Huge arguments: exact reduction with BigInt against 2/π to 1280 bits.
148
+
149
+ const PI_BITS = 1400
150
+ let twoOverPi = 0n
151
+ let halfPi130 = 0n
152
+
153
+ /** arctan(1/k) · 2^bits, by its Taylor series in fixed point. */
154
+ const arctanInverse = (k: bigint, bits: bigint): bigint => {
155
+ const one = 1n << bits
156
+ const k2 = k * k
157
+ let power = one / k
158
+ let sum = power
159
+ for (let i = 1n; power !== 0n; i++) {
160
+ power /= k2
161
+ const term = power / (2n * i + 1n)
162
+ sum = i % 2n === 1n ? sum - term : sum + term
163
+ }
164
+ return sum
165
+ }
166
+
167
+ const TWO_OVER_PI_BITS = 1280n
168
+
169
+ const initReduction = (): void => {
170
+ const bits = BigInt(PI_BITS)
171
+ // Machin: π = 16·atan(1/5) − 4·atan(1/239)
172
+ const pi = 16n * arctanInverse(5n, bits) - 4n * arctanInverse(239n, bits)
173
+ twoOverPi = (1n << (TWO_OVER_PI_BITS + 1n + bits)) / pi
174
+ halfPi130 = pi >> (bits - 129n)
175
+ }
176
+
177
+ const remPio2Large = (x: number): number => {
178
+ if (twoOverPi === 0n) initReduction()
179
+ const negative = x < 0
180
+ const ax = negative ? -x : x
181
+ // ax = mantissa · 2^exponent, exactly (ax >= 2^20 here, so it is normal).
182
+ const exponent = ((highWord(ax) >> 20) & 0x7ff) - 1075
183
+ const mantissa = BigInt(ax / fromWords((exponent + 1023) << 20, 0))
184
+ // ax · 2/π = product / 2^shift
185
+ const shift = TWO_OVER_PI_BITS - BigInt(exponent)
186
+ const product = mantissa * twoOverPi
187
+ const unit = 1n << shift
188
+ let n = Number((product >> shift) & 3n)
189
+ let fraction = product & (unit - 1n)
190
+ if (fraction >= unit >> 1n) {
191
+ fraction -= unit
192
+ n = (n + 1) & 3
193
+ }
194
+ // Keep 250 fraction bits, multiply by π/2 (130 bits): r = fraction·π/2 · 2^-380
195
+ const r = (fraction >> (shift - 250n)) * halfPi130
196
+ const scale = fromWords((380 + 1023) << 20, 0)
197
+ const high = Number(r) / scale
198
+ const low = Number(r - BigInt(high * scale)) / scale
199
+ reducedHigh = negative ? -high : high
200
+ reducedLow = negative ? -low : low
201
+ return negative ? -n : n
202
+ }
203
+
204
+ // ---------------------------------------------------------------------------
205
+ // Kernels on [-π/4, π/4]
206
+
207
+ const S1 = -1.66666666666666324348e-01
208
+ const S2 = 8.33333333332248946124e-03
209
+ const S3 = -1.98412698298579493134e-04
210
+ const S4 = 2.75573137070700676789e-06
211
+ const S5 = -2.50507602534068634195e-08
212
+ const S6 = 1.58969099521155010221e-10
213
+
214
+ const kernelSin = (x: number, y: number, hasTail: boolean): number => {
215
+ const z = x * x
216
+ const w = z * z
217
+ const r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6)
218
+ const v = z * x
219
+ if (!hasTail) return x + v * (S1 + z * r)
220
+ return x - ((z * (0.5 * y - v * r) - y) - v * S1)
221
+ }
222
+
223
+ const C1 = 4.16666666666666019037e-02
224
+ const C2 = -1.38888888888741095749e-03
225
+ const C3 = 2.48015872894767294178e-05
226
+ const C4 = -2.75573143513906633035e-07
227
+ const C5 = 2.08757232129817482790e-09
228
+ const C6 = -1.13596475577881948265e-11
229
+
230
+ const kernelCos = (x: number, y: number): number => {
231
+ const z = x * x
232
+ const w = z * z
233
+ const r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6))
234
+ const hz = 0.5 * z
235
+ const v = 1.0 - hz
236
+ return v + (((1.0 - v) - hz) + (z * r - x * y))
237
+ }
238
+
239
+ const T = [
240
+ 3.33333333333334091986e-01,
241
+ 1.33333333333201242699e-01,
242
+ 5.39682539762260521377e-02,
243
+ 2.18694882948595424599e-02,
244
+ 8.86323982359930005737e-03,
245
+ 3.59207910759131235356e-03,
246
+ 1.45620945432529025516e-03,
247
+ 5.88041240820264096874e-04,
248
+ 2.46463134818469906812e-04,
249
+ 7.81794442939557092300e-05,
250
+ 7.14072491382608190305e-05,
251
+ -1.85586374855275456654e-05,
252
+ 2.59073051863633712884e-05
253
+ ] as const
254
+ const PIO4_LO = 3.06161699786838301793e-17
255
+
256
+ /** tan(x + y) when `odd` is false, -1/tan(x + y) when it is true. */
257
+ const kernelTan = (xIn: number, yIn: number, odd: boolean): number => {
258
+ let x = xIn
259
+ let y = yIn
260
+ const hx = highWord(x)
261
+ const big = (hx & 0x7fffffff) >= 0x3fe59428 // |x| >= 0.6744
262
+ const negative = hx < 0
263
+ if (big) {
264
+ if (negative) {
265
+ x = -x
266
+ y = -y
267
+ }
268
+ x = (PIO4 - x) + (PIO4_LO - y)
269
+ y = 0.0
270
+ }
271
+ const z = x * x
272
+ let w = z * z
273
+ let r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11]))))
274
+ let v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12])))))
275
+ let s = z * x
276
+ r = y + z * (s * (r + v) + y) + s * T[0]
277
+ w = x + r
278
+ if (big) {
279
+ s = odd ? -1 : 1
280
+ v = s - 2.0 * (x + (r - w * w / (w + s)))
281
+ return negative ? -v : v
282
+ }
283
+ if (!odd) return w
284
+ // -1/(x + r) has up to 2 ulp error, so compute it accurately.
285
+ const w0 = clearLow(w)
286
+ v = r - (w0 - x)
287
+ const a = -1.0 / w
288
+ const a0 = clearLow(a)
289
+ return a0 + a * (1.0 + a0 * w0 + a0 * v)
290
+ }
291
+
292
+ // ---------------------------------------------------------------------------
293
+ // Trigonometric functions
294
+
295
+ export const sin = (x: number): number => {
296
+ const ix = highWord(x) & 0x7fffffff
297
+ if (ix <= 0x3fe921fb) {
298
+ if (ix < 0x3e500000) return x // |x| < 2^-26
299
+ return kernelSin(x, 0, false)
300
+ }
301
+ if (ix >= 0x7ff00000) return x - x
302
+ const n = remPio2(x)
303
+ switch (n & 3) {
304
+ case 0:
305
+ return kernelSin(reducedHigh, reducedLow, true)
306
+ case 1:
307
+ return kernelCos(reducedHigh, reducedLow)
308
+ case 2:
309
+ return -kernelSin(reducedHigh, reducedLow, true)
310
+ default:
311
+ return -kernelCos(reducedHigh, reducedLow)
312
+ }
313
+ }
314
+
315
+ export const cos = (x: number): number => {
316
+ const ix = highWord(x) & 0x7fffffff
317
+ if (ix <= 0x3fe921fb) {
318
+ if (ix < 0x3e46a09e) return 1.0 // |x| < 2^-27·√2
319
+ return kernelCos(x, 0)
320
+ }
321
+ if (ix >= 0x7ff00000) return x - x
322
+ const n = remPio2(x)
323
+ switch (n & 3) {
324
+ case 0:
325
+ return kernelCos(reducedHigh, reducedLow)
326
+ case 1:
327
+ return -kernelSin(reducedHigh, reducedLow, true)
328
+ case 2:
329
+ return -kernelCos(reducedHigh, reducedLow)
330
+ default:
331
+ return kernelSin(reducedHigh, reducedLow, true)
332
+ }
333
+ }
334
+
335
+ export const tan = (x: number): number => {
336
+ const ix = highWord(x) & 0x7fffffff
337
+ if (ix <= 0x3fe921fb) {
338
+ if (ix < 0x3e400000) return x // |x| < 2^-27
339
+ return kernelTan(x, 0.0, false)
340
+ }
341
+ if (ix >= 0x7ff00000) return x - x
342
+ const n = remPio2(x)
343
+ return kernelTan(reducedHigh, reducedLow, (n & 1) !== 0)
344
+ }
345
+
346
+ // ---------------------------------------------------------------------------
347
+ // Inverse trigonometric functions
348
+
349
+ const PIO2_HI = 1.57079632679489655800e+00
350
+ const PIO2_LO = 6.12323399573676603587e-17
351
+ const PS0 = 1.66666666666666657415e-01
352
+ const PS1 = -3.25565818622400915405e-01
353
+ const PS2 = 2.01212532134862925881e-01
354
+ const PS3 = -4.00555345006794114027e-02
355
+ const PS4 = 7.91534994289814532176e-04
356
+ const PS5 = 3.47933107596021167570e-05
357
+ const QS1 = -2.40339491173441421878e+00
358
+ const QS2 = 2.02094576023350569471e+00
359
+ const QS3 = -6.88283971605453293030e-01
360
+ const QS4 = 7.70381505559019352791e-02
361
+
362
+ const asinRatio = (z: number): number => {
363
+ const p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))))
364
+ const q = 1.0 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)))
365
+ return p / q
366
+ }
367
+
368
+ export const asin = (x: number): number => {
369
+ const hx = highWord(x)
370
+ const ix = hx & 0x7fffffff
371
+ if (ix >= 0x3ff00000) {
372
+ // |x| >= 1 or NaN
373
+ if (((ix - 0x3ff00000) | lowWord(x)) === 0) return x * PIO2_HI
374
+ return 0 / (x - x)
375
+ }
376
+ if (ix < 0x3fe00000) {
377
+ // |x| < 0.5
378
+ if (ix < 0x3e500000 && ix >= 0x00100000) return x
379
+ return x + x * asinRatio(x * x)
380
+ }
381
+ // 0.5 <= |x| < 1
382
+ const z = (1 - Math.abs(x)) * 0.5
383
+ const s = Math.sqrt(z)
384
+ const r = asinRatio(z)
385
+ let result: number
386
+ if (ix >= 0x3fef3333) {
387
+ // |x| > 0.975
388
+ result = PIO2_HI - (2 * (s + s * r) - PIO2_LO)
389
+ } else {
390
+ const f = clearLow(s)
391
+ const c = (z - f * f) / (s + f)
392
+ result = 0.5 * PIO2_HI - (2 * s * r - (PIO2_LO - 2 * c) - (0.5 * PIO2_HI - 2 * f))
393
+ }
394
+ return hx < 0 ? -result : result
395
+ }
396
+
397
+ export const acos = (x: number): number => {
398
+ const hx = highWord(x)
399
+ const ix = hx & 0x7fffffff
400
+ if (ix >= 0x3ff00000) {
401
+ // |x| >= 1 or NaN
402
+ if (((ix - 0x3ff00000) | lowWord(x)) === 0) return hx < 0 ? 2 * PIO2_HI : 0
403
+ return 0 / (x - x)
404
+ }
405
+ if (ix < 0x3fe00000) {
406
+ // |x| < 0.5
407
+ if (ix <= 0x3c600000) return PIO2_HI // |x| < 2^-57
408
+ return PIO2_HI - (x - (PIO2_LO - x * asinRatio(x * x)))
409
+ }
410
+ if (hx < 0) {
411
+ // x < -0.5
412
+ const z = (1.0 + x) * 0.5
413
+ const s = Math.sqrt(z)
414
+ const w = asinRatio(z) * s - PIO2_LO
415
+ return 2 * (PIO2_HI - (s + w))
416
+ }
417
+ // x > 0.5
418
+ const z = (1.0 - x) * 0.5
419
+ const s = Math.sqrt(z)
420
+ const df = clearLow(s)
421
+ const c = (z - df * df) / (s + df)
422
+ const w = asinRatio(z) * s + c
423
+ return 2 * (df + w)
424
+ }
425
+
426
+ const ATAN_HI = [
427
+ 4.63647609000806093515e-01,
428
+ 7.85398163397448278999e-01,
429
+ 9.82793723247329054082e-01,
430
+ 1.57079632679489655800e+00
431
+ ] as const
432
+ const ATAN_LO = [
433
+ 2.26987774529616870924e-17,
434
+ 3.06161699786838301793e-17,
435
+ 1.39033110312309984516e-17,
436
+ 6.12323399573676603587e-17
437
+ ] as const
438
+ const AT = [
439
+ 3.33333333333329318027e-01,
440
+ -1.99999999998764832476e-01,
441
+ 1.42857142725034663711e-01,
442
+ -1.11111104054623557880e-01,
443
+ 9.09088713343650656196e-02,
444
+ -7.69187620504482999495e-02,
445
+ 6.66107313738753120669e-02,
446
+ -5.83357013379057348645e-02,
447
+ 4.97687799461593236017e-02,
448
+ -3.65315727442169155270e-02,
449
+ 1.62858201153657823623e-02
450
+ ] as const
451
+
452
+ export const atan = (xIn: number): number => {
453
+ let x = xIn
454
+ const hx = highWord(x)
455
+ const negative = hx < 0
456
+ const ix = hx & 0x7fffffff
457
+ if (ix >= 0x44100000) {
458
+ // |x| >= 2^66 or NaN
459
+ if (x !== x) return x
460
+ return negative ? -ATAN_HI[3] : ATAN_HI[3]
461
+ }
462
+ let id: number
463
+ if (ix < 0x3fdc0000) {
464
+ // |x| < 0.4375
465
+ if (ix < 0x3e400000) return x // |x| < 2^-27
466
+ id = -1
467
+ } else {
468
+ x = Math.abs(x)
469
+ if (ix < 0x3ff30000) {
470
+ // |x| < 1.1875
471
+ if (ix < 0x3fe60000) {
472
+ // 7/16 <= |x| < 11/16
473
+ id = 0
474
+ x = (2.0 * x - 1.0) / (2.0 + x)
475
+ } else {
476
+ // 11/16 <= |x| < 19/16
477
+ id = 1
478
+ x = (x - 1.0) / (x + 1.0)
479
+ }
480
+ } else if (ix < 0x40038000) {
481
+ // |x| < 2.4375
482
+ id = 2
483
+ x = (x - 1.5) / (1.0 + 1.5 * x)
484
+ } else {
485
+ // 2.4375 <= |x| < 2^66
486
+ id = 3
487
+ x = -1.0 / x
488
+ }
489
+ }
490
+ const z = x * x
491
+ const w = z * z
492
+ const s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10])))))
493
+ const s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9]))))
494
+ if (id < 0) return x - x * (s1 + s2)
495
+ const result = ATAN_HI[id]! - ((x * (s1 + s2) - ATAN_LO[id]!) - x)
496
+ return negative ? -result : result
497
+ }
498
+
499
+ const PI = 3.1415926535897931160e+00
500
+ const PI_LO = 1.2246467991473531772e-16
501
+
502
+ export const atan2 = (y: number, x: number): number => {
503
+ if (x !== x || y !== y) return x + y
504
+ const hx = highWord(x)
505
+ const lx = lowWord(x)
506
+ const hy = highWord(y)
507
+ const ly = lowWord(y)
508
+ if (((hx - 0x3ff00000) | lx) === 0) return atan(y) // x = 1
509
+ const m = ((hy >>> 31) & 1) | ((hx >>> 30) & 2) // 2·sign(x) + sign(y)
510
+ const ix = hx & 0x7fffffff
511
+ const iy = hy & 0x7fffffff
512
+ if ((iy | ly) === 0) {
513
+ // y = ±0
514
+ switch (m) {
515
+ case 0:
516
+ case 1:
517
+ return y
518
+ case 2:
519
+ return PI
520
+ default:
521
+ return -PI
522
+ }
523
+ }
524
+ if ((ix | lx) === 0) return m & 1 ? -PI / 2 : PI / 2 // x = ±0
525
+ if (ix === 0x7ff00000) {
526
+ // x = ±Infinity
527
+ if (iy === 0x7ff00000) {
528
+ switch (m) {
529
+ case 0:
530
+ return PI / 4
531
+ case 1:
532
+ return -PI / 4
533
+ case 2:
534
+ return 3 * PI / 4
535
+ default:
536
+ return -3 * PI / 4
537
+ }
538
+ }
539
+ switch (m) {
540
+ case 0:
541
+ return 0.0
542
+ case 1:
543
+ return -0.0
544
+ case 2:
545
+ return PI
546
+ default:
547
+ return -PI
548
+ }
549
+ }
550
+ // |y/x| > 2^64
551
+ if (ix + (64 << 20) < iy || iy === 0x7ff00000) return m & 1 ? -PI / 2 : PI / 2
552
+ // atan(|y/x|) without spurious underflow
553
+ const z = (m & 2) !== 0 && iy + (64 << 20) < ix ? 0 : atan(Math.abs(y / x))
554
+ switch (m) {
555
+ case 0:
556
+ return z
557
+ case 1:
558
+ return -z
559
+ case 2:
560
+ return PI - (z - PI_LO)
561
+ default:
562
+ return (z - PI_LO) - PI
563
+ }
564
+ }
565
+
566
+ // ---------------------------------------------------------------------------
567
+ // Exponential functions
568
+
569
+ const LN2_HI = 6.93147180369123816490e-01
570
+ const LN2_LO = 1.90821492927058770002e-10
571
+ const INV_LN2 = 1.44269504088896338700e+00
572
+ const P1 = 1.66666666666666019037e-01
573
+ const P2 = -2.77777777770155933842e-03
574
+ const P3 = 6.61375632143793436117e-05
575
+ const P4 = -1.65339022054652515390e-06
576
+ const P5 = 4.13813679705723846039e-08
577
+
578
+ export const exp = (xIn: number): number => {
579
+ let x = xIn
580
+ const hx = highWord(x)
581
+ const negative = hx < 0
582
+ const ix = hx & 0x7fffffff
583
+ if (ix >= 0x4086232b) {
584
+ // |x| >= 708.39 or NaN
585
+ if (x !== x) return x
586
+ if (x > 709.782712893383973096) return x * TWO_1023 // overflow
587
+ if (x < -745.13321910194110842) return 0 // underflow
588
+ }
589
+ if (x === 1) return 2.718281828459045 // Math.E: the reduction below lands 1 ulp above it
590
+ let hi = 0
591
+ let lo = 0
592
+ let k = 0
593
+ if (ix > 0x3fd62e42) {
594
+ // |x| > 0.5·ln2
595
+ if (ix >= 0x3ff0a2b2) {
596
+ // |x| >= 1.5·ln2
597
+ k = (INV_LN2 * x + (negative ? -0.5 : 0.5)) | 0
598
+ } else {
599
+ k = negative ? -1 : 1
600
+ }
601
+ hi = x - k * LN2_HI
602
+ lo = k * LN2_LO
603
+ x = hi - lo
604
+ } else if (ix > 0x3e300000) {
605
+ // |x| > 2^-28
606
+ hi = x
607
+ } else {
608
+ return 1 + x
609
+ }
610
+ const xx = x * x
611
+ const c = x - xx * (P1 + xx * (P2 + xx * (P3 + xx * (P4 + xx * P5))))
612
+ const y = 1 + (x * c / (2 - c) - lo + hi)
613
+ return k === 0 ? y : scalbn(y, k)
614
+ }
615
+
616
+ const O_THRESHOLD = 7.09782712893383973096e+02
617
+ const Q1 = -3.33333333333331316428e-02
618
+ const Q2 = 1.58730158725481460165e-03
619
+ const Q3 = -7.93650757867487942473e-05
620
+ const Q4 = 4.00821782732936239552e-06
621
+ const Q5 = -2.01099218183624371326e-07
622
+
623
+ /** e^x − 1, accurate near 0. */
624
+ export const expm1 = (xIn: number): number => {
625
+ let x = xIn
626
+ const hx = highWord(x)
627
+ const negative = hx < 0
628
+ const ix = hx & 0x7fffffff
629
+ if (ix >= 0x4043687a) {
630
+ // |x| >= 56·ln2
631
+ if (x !== x) return x
632
+ if (negative) return -1
633
+ if (x > O_THRESHOLD) return x * TWO_1023
634
+ }
635
+ let k: number
636
+ let c = 0
637
+ if (ix > 0x3fd62e42) {
638
+ // |x| > 0.5·ln2
639
+ let hi: number
640
+ let lo: number
641
+ if (ix < 0x3ff0a2b2) {
642
+ // |x| < 1.5·ln2
643
+ if (!negative) {
644
+ hi = x - LN2_HI
645
+ lo = LN2_LO
646
+ k = 1
647
+ } else {
648
+ hi = x + LN2_HI
649
+ lo = -LN2_LO
650
+ k = -1
651
+ }
652
+ } else {
653
+ k = (INV_LN2 * x + (negative ? -0.5 : 0.5)) | 0
654
+ hi = x - k * LN2_HI
655
+ lo = k * LN2_LO
656
+ }
657
+ x = hi - lo
658
+ c = (hi - x) - lo
659
+ } else if (ix < 0x3c900000) {
660
+ return x // |x| < 2^-54
661
+ } else {
662
+ k = 0
663
+ }
664
+ const hfx = 0.5 * x
665
+ const hxs = x * hfx
666
+ const r1 = 1.0 + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))))
667
+ const t = 3.0 - r1 * hfx
668
+ let e = hxs * ((r1 - t) / (6.0 - x * t))
669
+ if (k === 0) return x - (x * e - hxs)
670
+ e = x * (e - c) - c
671
+ e -= hxs
672
+ if (k === -1) return 0.5 * (x - e) - 0.5
673
+ if (k === 1) {
674
+ if (x < -0.25) return -2.0 * (e - (x + 0.5))
675
+ return 1.0 + 2.0 * (x - e)
676
+ }
677
+ if (k < 0 || k > 56) {
678
+ const y = x - e + 1.0
679
+ return (k === 1024 ? y * 2.0 * TWO_1023 : y * fromWords((0x3ff + k) << 20, 0)) - 1.0
680
+ }
681
+ const twopk = fromWords((0x3ff + k) << 20, 0)
682
+ const twomk = fromWords((0x3ff - k) << 20, 0)
683
+ if (k < 20) return (x - e + (1 - twomk)) * twopk
684
+ return (x - (e + twomk) + 1) * twopk
685
+ }
686
+
687
+ export const tanh = (xIn: number): number => {
688
+ const negative = highWord(xIn) < 0
689
+ const x = Math.abs(xIn)
690
+ const w = highWord(x)
691
+ let t: number
692
+ if (w > 0x3fe193ea) {
693
+ // |x| > log(3)/2 or NaN
694
+ if (w > 0x40340000) {
695
+ t = 1 - 0 / x // |x| > 20 or NaN
696
+ } else {
697
+ t = expm1(2 * x)
698
+ t = 1 - 2 / (t + 2)
699
+ }
700
+ } else if (w > 0x3fd058ae) {
701
+ // |x| > log(5/3)/2
702
+ t = expm1(2 * x)
703
+ t = t / (t + 2)
704
+ } else if (w >= 0x00100000) {
705
+ t = expm1(-2 * x)
706
+ t = -t / (t + 2)
707
+ } else {
708
+ t = x // subnormal
709
+ }
710
+ return negative ? -t : t
711
+ }
712
+
713
+ // ---------------------------------------------------------------------------
714
+ // Power
715
+
716
+ const BP = [1.0, 1.5] as const
717
+ const DP_H = [0.0, 5.84962487220764160156e-01] as const
718
+ const DP_L = [0.0, 1.35003920212974897128e-08] as const
719
+ const HUGE = 1.0e300
720
+ const TINY = 1.0e-300
721
+ const L1 = 5.99999999999994648725e-01
722
+ const L2 = 4.28571428578550184252e-01
723
+ const L3 = 3.33333329818377432918e-01
724
+ const L4 = 2.72728123808534006489e-01
725
+ const L5 = 2.30660745775561754067e-01
726
+ const L6 = 2.06975017800338417784e-01
727
+ const LG2 = 6.93147180559945286227e-01
728
+ const LG2_H = 6.93147182464599609375e-01
729
+ const LG2_L = -1.90465429995776804525e-09
730
+ const OVT = 8.0085662595372944372e-17
731
+ const CP = 9.61796693925975554329e-01
732
+ const CP_H = 9.61796700954437255859e-01
733
+ const CP_L = -7.02846165095275826516e-09
734
+ const IVLN2 = 1.44269504088896338700e+00
735
+ const IVLN2_H = 1.44269502162933349609e+00
736
+ const IVLN2_L = 1.92596299112661746887e-08
737
+
738
+ export const pow = (x: number, y: number): number => {
739
+ // ECMAScript Number::exponentiate, where it differs from C pow.
740
+ if (y !== y) return NaN
741
+ if (y === 0) return 1
742
+ if (x !== x) return NaN
743
+ const hx = highWord(x)
744
+ const lx = lowWord(x)
745
+ const hy = highWord(y)
746
+ const ly = lowWord(y)
747
+ let ix = hx & 0x7fffffff
748
+ const iy = hy & 0x7fffffff
749
+ if (iy === 0x7ff00000 && ly === 0 && ((ix - 0x3ff00000) | lx) === 0) return NaN // (±1) ** ±Infinity
750
+ if (hx === 0x3ff00000 && lx === 0) return 1.0 // 1 ** y
751
+
752
+ // yisint: 0 when y is not an integer, 1 when odd, 2 when even (only when x < 0).
753
+ let yisint = 0
754
+ if (hx < 0) {
755
+ if (iy >= 0x43400000) {
756
+ yisint = 2
757
+ } else if (iy >= 0x3ff00000) {
758
+ const e = (iy >> 20) - 0x3ff
759
+ if (e > 20) {
760
+ const j = ly >>> (52 - e)
761
+ if (((j << (52 - e)) >>> 0) === ly) yisint = 2 - (j & 1)
762
+ } else if (ly === 0) {
763
+ const j = iy >> (20 - e)
764
+ if ((j << (20 - e)) === iy) yisint = 2 - (j & 1)
765
+ }
766
+ }
767
+ }
768
+
769
+ if (ly === 0) {
770
+ if (iy === 0x7ff00000) {
771
+ // y = ±Infinity
772
+ if (ix >= 0x3ff00000) return hy >= 0 ? y : 0.0 // (|x| > 1) ** ±Infinity
773
+ return hy >= 0 ? 0.0 : -y // (|x| < 1) ** ±Infinity
774
+ }
775
+ if (iy === 0x3ff00000) return hy >= 0 ? x : 1 / x // y = ±1
776
+ if (hy === 0x40000000) return x * x // y = 2
777
+ if (hy === 0x3fe00000 && hx >= 0) return Math.sqrt(x) // y = 0.5, x >= +0
778
+ }
779
+
780
+ let ax = Math.abs(x)
781
+ if (lx === 0 && (ix === 0x7ff00000 || ix === 0 || ix === 0x3ff00000)) {
782
+ // x = ±0, ±Infinity, ±1
783
+ let z = ax
784
+ if (hy < 0) z = 1.0 / z
785
+ if (hx < 0) {
786
+ if (((ix - 0x3ff00000) | yisint) === 0) {
787
+ z = (z - z) / (z - z) // (-1) ** non-integer
788
+ } else if (yisint === 1) {
789
+ z = -z
790
+ }
791
+ }
792
+ return z
793
+ }
794
+
795
+ let s = 1.0 // sign of the result
796
+ if (hx < 0) {
797
+ if (yisint === 0) return (x - x) / (x - x) // (x < 0) ** non-integer
798
+ if (yisint === 1) s = -1.0
799
+ }
800
+
801
+ let t1: number
802
+ let t2: number
803
+ if (iy > 0x41e00000) {
804
+ // |y| > 2^31
805
+ if (iy > 0x43f00000) {
806
+ // |y| > 2^64: must overflow or underflow
807
+ if (ix <= 0x3fefffff) return hy < 0 ? HUGE * HUGE : TINY * TINY
808
+ if (ix >= 0x3ff00000) return hy > 0 ? HUGE * HUGE : TINY * TINY
809
+ }
810
+ // Overflow or underflow when x is not close to one.
811
+ if (ix < 0x3fefffff) return hy < 0 ? s * HUGE * HUGE : s * TINY * TINY
812
+ if (ix > 0x3ff00000) return hy > 0 ? s * HUGE * HUGE : s * TINY * TINY
813
+ // |1 - x| <= 2^-20: log(x) by x - x^2/2 + x^3/3 - x^4/4
814
+ const t = ax - 1.0
815
+ const w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25))
816
+ const u = IVLN2_H * t
817
+ const v = t * IVLN2_L - w * IVLN2
818
+ t1 = clearLow(u + v)
819
+ t2 = v - (t1 - u)
820
+ } else {
821
+ let n = 0
822
+ if (ix < 0x00100000) {
823
+ // subnormal x
824
+ ax *= TWO_53
825
+ n -= 53
826
+ ix = highWord(ax)
827
+ }
828
+ n += (ix >> 20) - 0x3ff
829
+ const j = ix & 0x000fffff
830
+ ix = j | 0x3ff00000
831
+ let k: 0 | 1
832
+ if (j <= 0x3988e) {
833
+ k = 0 // |x| < sqrt(3/2)
834
+ } else if (j < 0xbb67a) {
835
+ k = 1 // |x| < sqrt(3)
836
+ } else {
837
+ k = 0
838
+ n += 1
839
+ ix -= 0x00100000
840
+ }
841
+ ax = fromWords(ix, lowWord(ax))
842
+ // ss = s_h + s_l = (x - 1)/(x + 1) or (x - 1.5)/(x + 1.5)
843
+ let u = ax - BP[k]
844
+ let v = 1.0 / (ax + BP[k])
845
+ const ss = u * v
846
+ const sH = clearLow(ss)
847
+ let tH = fromWords(((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18), 0)
848
+ let tL = ax - (tH - BP[k])
849
+ const sL = v * ((u - sH * tH) - sH * tL)
850
+ // log(ax)
851
+ let s2 = ss * ss
852
+ let r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))))
853
+ r += sL * (sH + ss)
854
+ s2 = sH * sH
855
+ tH = clearLow(3.0 + s2 + r)
856
+ tL = r - ((tH - 3.0) - s2)
857
+ u = sH * tH
858
+ v = sL * tH + tL * ss
859
+ const pH = clearLow(u + v)
860
+ const pL = v - (pH - u)
861
+ const zH = CP_H * pH
862
+ const zL = CP_L * pH + pL * CP + DP_L[k]
863
+ const t = n
864
+ t1 = clearLow(((zH + zL) + DP_H[k]) + t)
865
+ t2 = zL - (((t1 - t) - DP_H[k]) - zH)
866
+ }
867
+
868
+ // (y1 + y2)·(t1 + t2)
869
+ const y1 = clearLow(y)
870
+ const pL = (y - y1) * t1 + y * t2
871
+ let pH = y1 * t1
872
+ let z = pL + pH
873
+ let j = highWord(z)
874
+ const i = lowWord(z)
875
+ if (j >= 0x40900000) {
876
+ // z >= 1024
877
+ if (((j - 0x40900000) | i) !== 0) return s * HUGE * HUGE
878
+ if (pL + OVT > z - pH) return s * HUGE * HUGE
879
+ } else if ((j & 0x7fffffff) >= 0x4090cc00) {
880
+ // z <= -1075
881
+ if (((j - (0xc090cc00 | 0)) | i) !== 0) return s * TINY * TINY
882
+ if (pL <= z - pH) return s * TINY * TINY
883
+ }
884
+
885
+ // 2^(pH + pL)
886
+ const abs = j & 0x7fffffff
887
+ let k = (abs >> 20) - 0x3ff
888
+ let n = 0
889
+ if (abs > 0x3fe00000) {
890
+ // |z| > 0.5: n = [z + 0.5]
891
+ n = j + (0x00100000 >> (k + 1))
892
+ k = ((n & 0x7fffffff) >> 20) - 0x3ff
893
+ const t = fromWords(n & ~(0x000fffff >> k), 0)
894
+ n = ((n & 0x000fffff) | 0x00100000) >> (20 - k)
895
+ if (j < 0) n = -n
896
+ pH -= t
897
+ }
898
+ const t = clearLow(pL + pH)
899
+ const u = t * LG2_H
900
+ const v = (pL - (t - pH)) * LG2 + t * LG2_L
901
+ z = u + v
902
+ const w = v - (z - u)
903
+ const tt = z * z
904
+ const r1 = z - tt * (P1 + tt * (P2 + tt * (P3 + tt * (P4 + tt * P5))))
905
+ const r = (z * r1) / (r1 - 2.0) - (w + z * w)
906
+ z = 1.0 - (r - z)
907
+ j = highWord(z)
908
+ j += n << 20
909
+ if ((j >> 20) <= 0) {
910
+ z = scalbn(z, n) // subnormal result
911
+ } else {
912
+ z = fromWords(j, lowWord(z))
913
+ }
914
+ return s * z
915
+ }
916
+
917
+ // ---------------------------------------------------------------------------
918
+ // hypot
919
+
920
+ const SPLIT = 134217729 // 2^27 + 1
921
+ const TWO_700 = fromWords((700 + 1023) << 20, 0)
922
+ const TWO_M700 = fromWords((-700 + 1023) << 20, 0)
923
+
924
+ export const hypot = (xIn: number, yIn: number): number => {
925
+ let hx = highWord(xIn) & 0x7fffffff
926
+ let lx = lowWord(xIn)
927
+ let hy = highWord(yIn) & 0x7fffffff
928
+ let ly = lowWord(yIn)
929
+ // Arrange |x| >= |y| by their bits, so NaN sorts above Infinity.
930
+ if (hx < hy || (hx === hy && lx < ly)) {
931
+ const th = hx
932
+ const tl = lx
933
+ hx = hy
934
+ lx = ly
935
+ hy = th
936
+ ly = tl
937
+ }
938
+ const ex = hx >>> 20
939
+ const ey = hy >>> 20
940
+ let x = fromWords(hx, lx)
941
+ let y = fromWords(hy, ly)
942
+ if (ey === 0x7ff) return y // hypot(Infinity, NaN) is Infinity
943
+ if (ex === 0x7ff || (hy | ly) === 0) return x
944
+ if (ex - ey > 64) return x + y
945
+ // Scale so xh·xh cannot overflow and xl·xl cannot underflow.
946
+ let z = 1
947
+ if (ex > 0x3ff + 510) {
948
+ z = TWO_700
949
+ x *= TWO_M700
950
+ y *= TWO_M700
951
+ } else if (ey < 0x3ff - 450) {
952
+ z = TWO_M700
953
+ x *= TWO_700
954
+ y *= TWO_700
955
+ }
956
+ // x² and y² as exact double-double sums (Dekker split).
957
+ let c = x * SPLIT
958
+ const xh = x - c + c
959
+ const xl = x - xh
960
+ const hxx = x * x
961
+ const lxx = xh * xh - hxx + 2 * xh * xl + xl * xl
962
+ c = y * SPLIT
963
+ const yh = y - c + c
964
+ const yl = y - yh
965
+ const hyy = y * y
966
+ const lyy = yh * yh - hyy + 2 * yh * yl + yl * yl
967
+ return z * Math.sqrt(lyy + lxx + hyy + hxx)
968
+ }
969
+
970
+ // ---------------------------------------------------------------------------
971
+ // Logarithms
972
+
973
+ const LOG1 = 6.666666666666735130e-01
974
+ const LOG2 = 3.999999999940941908e-01
975
+ const LOG3 = 2.857142874366239149e-01
976
+ const LOG4 = 2.222219843214978396e-01
977
+ const LOG5 = 1.818357216161805012e-01
978
+ const LOG6 = 1.531383769920937332e-01
979
+ const LOG7 = 1.479819860511658591e-01
980
+ const TWO_54 = fromWords(0x43500000, 0)
981
+
982
+ let logK = 0
983
+ let logF = 0
984
+
985
+ /**
986
+ * Splits a positive finite non-unit `x` into `2^logK · (1 + logF)` with
987
+ * `1 + logF` in [√2/2, √2]. Returns a result for the special cases
988
+ * (±0, negative, NaN, Infinity), or `undefined` once split.
989
+ */
990
+ const logSplit = (xIn: number): number | undefined => {
991
+ let x = xIn
992
+ let hx = highWord(x) >>> 0
993
+ let k = 0
994
+ if (hx < 0x00100000 || hx >>> 31 !== 0) {
995
+ if (x === 0) return -1 / (x * x) // log(±0) = -Infinity
996
+ if (hx >>> 31 !== 0) return (x - x) / 0.0 // log(negative) = NaN
997
+ k -= 54 // subnormal: scale up
998
+ x *= TWO_54
999
+ hx = highWord(x) >>> 0
1000
+ } else if (hx >= 0x7ff00000) {
1001
+ return x // Infinity or NaN
1002
+ } else if (hx === 0x3ff00000 && lowWord(x) === 0) {
1003
+ return 0 // log(1) = +0
1004
+ }
1005
+ hx += 0x3ff00000 - 0x3fe6a09e
1006
+ k += (hx >>> 20) - 0x3ff
1007
+ hx = (hx & 0x000fffff) + 0x3fe6a09e
1008
+ logK = k
1009
+ logF = fromWords(hx, lowWord(x)) - 1.0
1010
+ return undefined
1011
+ }
1012
+
1013
+ /** s·(hfsq + R) of the log kernel on f = logF. */
1014
+ const logKernel = (f: number, hfsq: number): number => {
1015
+ const s = f / (2.0 + f)
1016
+ const z = s * s
1017
+ const w = z * z
1018
+ const t1 = w * (LOG2 + w * (LOG4 + w * LOG6))
1019
+ const t2 = z * (LOG1 + w * (LOG3 + w * (LOG5 + w * LOG7)))
1020
+ return s * (hfsq + t2 + t1)
1021
+ }
1022
+
1023
+ export const log = (x: number): number => {
1024
+ const special = logSplit(x)
1025
+ if (special !== undefined) return special
1026
+ const f = logF
1027
+ const hfsq = 0.5 * f * f
1028
+ const dk = logK
1029
+ return logKernel(f, hfsq) + dk * LN2_LO - hfsq + f + dk * LN2_HI
1030
+ }
1031
+
1032
+ const IVLN2HI = 1.44269504072144627571e+00
1033
+ const IVLN2LO = 1.67517131648865118353e-10
1034
+
1035
+ export const log2 = (x: number): number => {
1036
+ const special = logSplit(x)
1037
+ if (special !== undefined) return special
1038
+ const f = logF
1039
+ const hfsq = 0.5 * f * f
1040
+ const hi = clearLow(f - hfsq)
1041
+ const lo = f - hi - hfsq + logKernel(f, hfsq)
1042
+ let valHi = hi * IVLN2HI
1043
+ let valLo = (lo + hi) * IVLN2LO + lo * IVLN2HI
1044
+ const y = logK
1045
+ const w = y + valHi
1046
+ valLo += (y - w) + valHi
1047
+ valHi = w
1048
+ return valLo + valHi
1049
+ }
1050
+
1051
+ const IVLN10HI = 4.34294481878168880939e-01
1052
+ const IVLN10LO = 2.50829467116452752298e-11
1053
+ const LOG10_2HI = 3.01029995663611771306e-01
1054
+ const LOG10_2LO = 3.69423907715893078616e-13
1055
+
1056
+ export const log10 = (x: number): number => {
1057
+ const special = logSplit(x)
1058
+ if (special !== undefined) return special
1059
+ const f = logF
1060
+ const hfsq = 0.5 * f * f
1061
+ const hi = clearLow(f - hfsq)
1062
+ const lo = f - hi - hfsq + logKernel(f, hfsq)
1063
+ let valHi = hi * IVLN10HI
1064
+ const dk = logK
1065
+ const y = dk * LOG10_2HI
1066
+ let valLo = dk * LOG10_2LO + (lo + hi) * IVLN10LO + lo * IVLN10HI
1067
+ const w = y + valHi
1068
+ valLo += (y - w) + valHi
1069
+ valHi = w
1070
+ return valLo + valHi
1071
+ }
1072
+
1073
+ export const log1p = (x: number): number => {
1074
+ const hx = highWord(x) >>> 0
1075
+ let k = 1
1076
+ let c = 0
1077
+ let f = 0
1078
+ if (hx < 0x3fda827a || hx >>> 31 !== 0) {
1079
+ // 1 + x < √2
1080
+ if (hx >= 0xbff00000) {
1081
+ // x <= -1
1082
+ if (x === -1) return x / 0.0 // -Infinity
1083
+ return (x - x) / 0.0 // NaN
1084
+ }
1085
+ if (((hx << 1) >>> 0) < 0x79400000) return x // |x| < 2^-53
1086
+ if (hx <= 0xbfd2bec4) {
1087
+ // √2/2 <= 1 + x < √2
1088
+ k = 0
1089
+ f = x
1090
+ }
1091
+ } else if (hx >= 0x7ff00000) {
1092
+ return x
1093
+ }
1094
+ if (k !== 0) {
1095
+ const u = 1 + x
1096
+ let hu = highWord(u) >>> 0
1097
+ hu += 0x3ff00000 - 0x3fe6a09e
1098
+ k = (hu >>> 20) - 0x3ff
1099
+ // Correction term ~ log(1 + x) - log(u), avoiding underflow in c/u.
1100
+ if (k < 54) {
1101
+ c = k >= 2 ? 1 - (u - x) : x - (u - 1)
1102
+ c /= u
1103
+ } else {
1104
+ c = 0
1105
+ }
1106
+ hu = (hu & 0x000fffff) + 0x3fe6a09e
1107
+ f = fromWords(hu, lowWord(u)) - 1
1108
+ }
1109
+ const hfsq = 0.5 * f * f
1110
+ const dk = k
1111
+ return logKernel(f, hfsq) + (dk * LN2_LO + c) - hfsq + f + dk * LN2_HI
1112
+ }
1113
+
1114
+ // ---------------------------------------------------------------------------
1115
+ // Hyperbolic functions
1116
+
1117
+ const EXPO2_KLN2 = fromWords(0x40962066, 0x151add8b) // 2043·ln2 (musl __expo2)
1118
+ const EXPO2_SCALE = fromWords((0x3ff + 1021) << 20, 0) // 2^1021
1119
+
1120
+ /** exp(x)/2·sign for x > log(DBL_MAX): exp(x - 2043·ln2)·2^2042, without overflowing early. */
1121
+ const expo2 = (x: number, sign: number): number => exp(x - EXPO2_KLN2) * (sign * EXPO2_SCALE) * EXPO2_SCALE
1122
+
1123
+ export const sinh = (x: number): number => {
1124
+ const h = highWord(x) < 0 ? -0.5 : 0.5
1125
+ const absx = Math.abs(x)
1126
+ const w = highWord(absx)
1127
+ if (w < 0x40862e42) {
1128
+ // |x| < log(DBL_MAX)
1129
+ const t = expm1(absx)
1130
+ if (w < 0x3ff00000) {
1131
+ if (w < 0x3ff00000 - (26 << 20)) return x
1132
+ return h * (2 * t - t * t / (t + 1))
1133
+ }
1134
+ return h * (t + t / (t + 1))
1135
+ }
1136
+ return expo2(absx, 2 * h) // overflow or NaN
1137
+ }
1138
+
1139
+ export const cosh = (xIn: number): number => {
1140
+ const x = Math.abs(xIn)
1141
+ const w = highWord(x)
1142
+ if (w < 0x3fe62e42) {
1143
+ // |x| < log(2)
1144
+ if (w < 0x3ff00000 - (26 << 20)) return 1
1145
+ const t = expm1(x)
1146
+ return 1 + t * t / (2 * (1 + t))
1147
+ }
1148
+ if (w < 0x40862e42) {
1149
+ // |x| < log(DBL_MAX)
1150
+ const t = exp(x)
1151
+ return 0.5 * (t + 1 / t)
1152
+ }
1153
+ return expo2(x, 1.0) // overflow or NaN
1154
+ }
1155
+
1156
+ const LN2 = 6.93147180559945286227e-01
1157
+
1158
+ export const asinh = (x: number): number => {
1159
+ const hx = highWord(x)
1160
+ const ix = hx & 0x7fffffff
1161
+ if (ix >= 0x7ff00000) return x + x // Infinity or NaN
1162
+ if (ix < 0x3e300000) return x // |x| < 2^-28
1163
+ let w: number
1164
+ if (ix > 0x41b00000) {
1165
+ // |x| > 2^28
1166
+ w = log(Math.abs(x)) + LN2
1167
+ } else if (ix > 0x40000000) {
1168
+ // 2 < |x| <= 2^28
1169
+ const t = Math.abs(x)
1170
+ w = log(2.0 * t + 1 / (Math.sqrt(x * x + 1) + t))
1171
+ } else {
1172
+ // 2^-28 <= |x| <= 2
1173
+ const t = x * x
1174
+ w = log1p(Math.abs(x) + t / (1 + Math.sqrt(1 + t)))
1175
+ }
1176
+ return hx > 0 ? w : -w
1177
+ }
1178
+
1179
+ export const acosh = (x: number): number => {
1180
+ const hx = highWord(x)
1181
+ if (hx < 0x3ff00000) return (x - x) / (x - x) // x < 1 or negative NaN
1182
+ if (hx >= 0x41b00000) {
1183
+ // x > 2^28
1184
+ if (hx >= 0x7ff00000) return x + x // Infinity or NaN
1185
+ return log(x) + LN2
1186
+ }
1187
+ if (((hx - 0x3ff00000) | lowWord(x)) === 0) return 0 // acosh(1) = 0
1188
+ if (hx > 0x40000000) {
1189
+ // 2 < x <= 2^28
1190
+ const t = x * x
1191
+ return log(2.0 * x - 1 / (x + Math.sqrt(t - 1)))
1192
+ }
1193
+ // 1 < x <= 2
1194
+ const t = x - 1
1195
+ return log1p(t + Math.sqrt(2.0 * t + t * t))
1196
+ }
1197
+
1198
+ export const atanh = (xIn: number): number => {
1199
+ const hx = highWord(xIn)
1200
+ const lx = lowWord(xIn)
1201
+ const ix = hx & 0x7fffffff
1202
+ if ((ix | ((lx | ((-lx) >>> 0)) >>> 31)) > 0x3ff00000) return (xIn - xIn) / (xIn - xIn) // |x| > 1 or NaN
1203
+ if (ix === 0x3ff00000) return xIn / 0 // ±Infinity
1204
+ if (ix < 0x3e300000) return xIn // |x| < 2^-28
1205
+ const x = Math.abs(xIn)
1206
+ let t: number
1207
+ if (ix < 0x3fe00000) {
1208
+ // |x| < 0.5
1209
+ t = x + x
1210
+ t = 0.5 * log1p(t + t * x / (1 - x))
1211
+ } else {
1212
+ t = 0.5 * log1p((x + x) / (1 - x))
1213
+ }
1214
+ return hx >= 0 ? t : -t
1215
+ }
1216
+
1217
+ // ---------------------------------------------------------------------------
1218
+ // Cube root
1219
+
1220
+ const B1 = 715094163 // (1023 - 1023/3 - 0.03306235651)·2^20
1221
+ const B2 = 696219795 // (1023 - 1023/3 - 54/3 - 0.03306235651)·2^20
1222
+ const CP0 = 1.87595182427177009643
1223
+ const CP1 = -1.88497979543377169875
1224
+ const CP2 = 1.621429720105354466140
1225
+ const CP3 = -0.758397934778766047437
1226
+ const CP4 = 0.145996192886612446982
1227
+
1228
+ export const cbrt = (x: number): number => {
1229
+ const high = highWord(x)
1230
+ const sign = high & 0x80000000
1231
+ let hx = high & 0x7fffffff
1232
+ if (hx >= 0x7ff00000) return x + x // Infinity or NaN
1233
+ // Rough cube root to 5 bits.
1234
+ if (hx < 0x00100000) {
1235
+ // zero or subnormal
1236
+ hx = highWord(x * TWO_54) & 0x7fffffff
1237
+ if (hx === 0) return x // ±0
1238
+ hx = Math.floor(hx / 3) + B2
1239
+ } else {
1240
+ hx = Math.floor(hx / 3) + B1
1241
+ }
1242
+ let t = fromWords((sign | hx) >>> 0, 0)
1243
+ // New cube root to 23 bits.
1244
+ let r = (t * t) * (t / x)
1245
+ t = t * ((CP0 + r * (CP1 + r * CP2)) + ((r * r) * r) * (CP3 + r * CP4))
1246
+ // Round t away from zero to 23 bits.
1247
+ const sum = lowWord(t) + 0x80000000
1248
+ const carry = sum >= 0x100000000 ? 1 : 0
1249
+ t = fromWords(((highWord(t) >>> 0) + carry) >>> 0, (sum & 0xc0000000) >>> 0)
1250
+ // One Newton step to 53 bits, error < 0.667 ulp.
1251
+ const s = t * t
1252
+ r = x / s
1253
+ const w = t + t
1254
+ r = (r - t) / (w + r)
1255
+ return t + t * r
1256
+ }