@grain/stdlib 0.5.13 → 0.6.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.
- package/CHANGELOG.md +193 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/number.gr
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ====================================================
|
|
3
|
+
* Applies to all functions with a comment referring here.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
6
|
+
*
|
|
7
|
+
* Permission to use, copy, modify, and distribute this
|
|
8
|
+
* software is freely granted, provided that this notice
|
|
9
|
+
* is preserved.
|
|
10
|
+
*
|
|
11
|
+
* ====================================================
|
|
12
|
+
*/
|
|
13
|
+
|
|
1
14
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
15
|
+
* Utilities for working with numbers.
|
|
16
|
+
*
|
|
17
|
+
* @example from "number" include Number
|
|
18
|
+
*
|
|
19
|
+
* @example 1
|
|
20
|
+
* @example -1
|
|
21
|
+
* @example 0.5
|
|
22
|
+
* @example 1/2
|
|
23
|
+
* @example Infinity
|
|
24
|
+
* @example NaN
|
|
25
|
+
*
|
|
4
26
|
* @since v0.4.0
|
|
5
27
|
*/
|
|
28
|
+
module Number
|
|
6
29
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
30
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
31
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
32
|
+
from "runtime/unsafe/wasmf32" include WasmF32
|
|
33
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
34
|
+
from "runtime/unsafe/memory" include Memory
|
|
35
|
+
from "runtime/dataStructures" include DataStructures
|
|
36
|
+
use DataStructures.{ newFloat64, allocateString }
|
|
37
|
+
from "runtime/numbers" include Numbers
|
|
38
|
+
use Numbers.{
|
|
13
39
|
coerceNumberToWasmF64,
|
|
14
40
|
reducedInteger,
|
|
15
41
|
isFloat,
|
|
@@ -17,124 +43,100 @@ import {
|
|
|
17
43
|
isRational,
|
|
18
44
|
isBoxedNumber,
|
|
19
45
|
isNaN,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import Tags from "runtime/unsafe/tags"
|
|
26
|
-
import Exception from "runtime/exception"
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @section Constants: Number constant values.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* NaN represented as a Number value.
|
|
34
|
-
*
|
|
35
|
-
* @since v0.5.4
|
|
36
|
-
*/
|
|
37
|
-
export let nan = 0.0 / 0.0
|
|
46
|
+
}
|
|
47
|
+
from "runtime/atoi/parse" include Parse as Atoi
|
|
48
|
+
from "runtime/atof/parse" include Parse as Atof
|
|
49
|
+
from "runtime/unsafe/tags" include Tags
|
|
50
|
+
from "runtime/exception" include Exception
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
* Infinity represented as a Number value.
|
|
41
|
-
*
|
|
42
|
-
* @since v0.5.4
|
|
43
|
-
*/
|
|
44
|
-
export let infinity = 1.0 / 0.0
|
|
52
|
+
use Atoi.{ type ParseIntError }
|
|
45
53
|
|
|
54
|
+
provide { type ParseIntError }
|
|
46
55
|
/**
|
|
47
56
|
* Pi represented as a Number value.
|
|
48
57
|
*
|
|
49
58
|
* @since v0.5.2
|
|
50
59
|
*/
|
|
51
|
-
|
|
60
|
+
provide let pi = 3.141592653589793
|
|
52
61
|
|
|
53
62
|
/**
|
|
54
63
|
* Tau represented as a Number value.
|
|
55
64
|
*
|
|
56
65
|
* @since v0.5.2
|
|
57
66
|
*/
|
|
58
|
-
|
|
67
|
+
provide let tau = 6.283185307179586
|
|
59
68
|
|
|
60
69
|
/**
|
|
61
70
|
* Euler's number represented as a Number value.
|
|
62
71
|
*
|
|
63
72
|
* @since v0.5.2
|
|
64
73
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @section Operations: Functions for operating on values of the Number type.
|
|
69
|
-
*/
|
|
74
|
+
provide let e = 2.718281828459045
|
|
70
75
|
|
|
71
76
|
/**
|
|
72
77
|
* Computes the sum of its operands.
|
|
73
78
|
*
|
|
74
|
-
* @param
|
|
75
|
-
* @param
|
|
79
|
+
* @param num1: The first operand
|
|
80
|
+
* @param num2: The second operand
|
|
76
81
|
* @returns The sum of the two operands
|
|
77
82
|
*
|
|
78
|
-
* @
|
|
83
|
+
* @example
|
|
84
|
+
* from Number use { (+) }
|
|
85
|
+
* assert 1 + 2 == 3
|
|
86
|
+
*
|
|
87
|
+
* @since v0.6.0
|
|
88
|
+
* @history v0.4.0: Originally named `add`
|
|
79
89
|
*/
|
|
80
|
-
|
|
90
|
+
provide let (+) = (+)
|
|
81
91
|
|
|
82
92
|
/**
|
|
83
93
|
* Computes the difference of its operands.
|
|
84
94
|
*
|
|
85
|
-
* @param
|
|
86
|
-
* @param
|
|
95
|
+
* @param num1: The first operand
|
|
96
|
+
* @param num2: The second operand
|
|
87
97
|
* @returns The difference of the two operands
|
|
88
98
|
*
|
|
89
|
-
* @
|
|
99
|
+
* @example
|
|
100
|
+
* from Number use { (-) }
|
|
101
|
+
* assert 5 - 2 == 3
|
|
102
|
+
*
|
|
103
|
+
* @since v0.6.0
|
|
104
|
+
* @history v0.4.0: Originally named `sub`
|
|
90
105
|
*/
|
|
91
|
-
|
|
106
|
+
provide let (-) = (-)
|
|
92
107
|
|
|
93
108
|
/**
|
|
94
109
|
* Computes the product of its operands.
|
|
95
110
|
*
|
|
96
|
-
* @param
|
|
97
|
-
* @param
|
|
111
|
+
* @param num1: The first operand
|
|
112
|
+
* @param num2: The second operand
|
|
98
113
|
* @returns The product of the two operands
|
|
99
114
|
*
|
|
100
|
-
* @
|
|
115
|
+
* @example
|
|
116
|
+
* from Number use { (*) }
|
|
117
|
+
* assert 5 * 4 == 20
|
|
118
|
+
*
|
|
119
|
+
* @since v0.6.0
|
|
120
|
+
* @history v0.4.0: Originally named `mul`
|
|
101
121
|
*/
|
|
102
|
-
|
|
122
|
+
provide let (*) = (*)
|
|
103
123
|
|
|
104
124
|
/**
|
|
105
125
|
* Computes the quotient of its operands.
|
|
106
126
|
*
|
|
107
|
-
* @param
|
|
108
|
-
* @param
|
|
127
|
+
* @param num1: The dividend
|
|
128
|
+
* @param num2: The divisor
|
|
109
129
|
* @returns The quotient of the two operands
|
|
110
130
|
*
|
|
111
|
-
* @
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// Exponentiation by squaring https://en.wikipedia.org/wiki/Exponentiation_by_squaring special path for int^int
|
|
116
|
-
let rec expBySquaring = (y, x, n) => {
|
|
117
|
-
if (n == 0) {
|
|
118
|
-
1
|
|
119
|
-
} else if (n == 1) {
|
|
120
|
-
x * y
|
|
121
|
-
} else if (n % 2 == 0) {
|
|
122
|
-
expBySquaring(y, x * x, n / 2)
|
|
123
|
-
} else {
|
|
124
|
-
expBySquaring(x * y, x * x, (n - 1) / 2)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Math.pow is largely based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
129
|
-
/*
|
|
130
|
-
* ====================================================
|
|
131
|
-
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
131
|
+
* @example
|
|
132
|
+
* from Number use { (/) }
|
|
133
|
+
* assert 10 / 2.5 == 4
|
|
132
134
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* is preserved.
|
|
136
|
-
* ====================================================
|
|
135
|
+
* @since v0.6.0
|
|
136
|
+
* @history v0.4.0: Originally named `div`
|
|
137
137
|
*/
|
|
138
|
+
provide let (/) = (/)
|
|
139
|
+
|
|
138
140
|
/**
|
|
139
141
|
* Computes the exponentiation of the given base and power.
|
|
140
142
|
*
|
|
@@ -142,422 +144,14 @@ let rec expBySquaring = (y, x, n) => {
|
|
|
142
144
|
* @param power: The exponent number
|
|
143
145
|
* @returns The base raised to the given power
|
|
144
146
|
*
|
|
145
|
-
* @
|
|
147
|
+
* @example
|
|
148
|
+
* from Number use { (**) }
|
|
149
|
+
* assert 10 ** 2 == 100
|
|
150
|
+
*
|
|
151
|
+
* @since v0.6.0
|
|
152
|
+
* @history v0.5.4: Originally named `pow`
|
|
146
153
|
*/
|
|
147
|
-
|
|
148
|
-
export let pow = (base, power) => {
|
|
149
|
-
// TODO(#1476): Move this into runtime/numbers.gr
|
|
150
|
-
if (base == 1 && power != 0) {
|
|
151
|
-
1
|
|
152
|
-
} else if (
|
|
153
|
-
isInteger(WasmI32.fromGrain(base)) && isInteger(WasmI32.fromGrain(power))
|
|
154
|
-
) {
|
|
155
|
-
if (power < 0) expBySquaring(1, 1 / base, power * -1)
|
|
156
|
-
else expBySquaring(1, base, power)
|
|
157
|
-
} else {
|
|
158
|
-
// TODO(#553): Refactor once we have early return
|
|
159
|
-
// Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
|
|
160
|
-
let (==) = WasmF64.eq
|
|
161
|
-
let (!=) = WasmF64.ne
|
|
162
|
-
let (<=) = WasmF64.le
|
|
163
|
-
let (/) = WasmF64.div
|
|
164
|
-
let (*) = WasmF64.mul
|
|
165
|
-
let (+) = WasmF64.add
|
|
166
|
-
// Constants
|
|
167
|
-
let infinity = 1.0W / 0.0W
|
|
168
|
-
let nan = 0.0W / 0.0W
|
|
169
|
-
let x = coerceNumberToWasmF64(base)
|
|
170
|
-
let y = coerceNumberToWasmF64(power)
|
|
171
|
-
let mut foundOutput = false, output = 0.0W
|
|
172
|
-
// Fast paths
|
|
173
|
-
if (WasmF64.abs(y) <= 2.0W) {
|
|
174
|
-
if (y == 2.0W) {
|
|
175
|
-
foundOutput = true
|
|
176
|
-
output = x * x
|
|
177
|
-
} else if (y == 0.5W) {
|
|
178
|
-
foundOutput = true
|
|
179
|
-
if (x != infinity) output = WasmF64.abs(WasmF64.sqrt(x))
|
|
180
|
-
else output = infinity
|
|
181
|
-
} else if (y == -1.0W) {
|
|
182
|
-
foundOutput = true
|
|
183
|
-
output = 1.0W / x
|
|
184
|
-
} else if (y == 1.0W) {
|
|
185
|
-
foundOutput = true
|
|
186
|
-
output = x
|
|
187
|
-
} else if (y == 0.0W) {
|
|
188
|
-
foundOutput = true
|
|
189
|
-
output = nan
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// Full calculation
|
|
193
|
-
if (foundOutput) {
|
|
194
|
-
WasmI32.toGrain(newFloat64(output)): Number
|
|
195
|
-
} else {
|
|
196
|
-
let dp_h1 = WasmF64.reinterpretI64(0x3FE2B80340000000N)
|
|
197
|
-
let dp_l1 = WasmF64.reinterpretI64(0x3E4CFDEB43CFD006N)
|
|
198
|
-
let two53 = WasmF64.reinterpretI64(0x4340000000000000N)
|
|
199
|
-
let huge = WasmF64.reinterpretI64(0x7E37E43C8800759CN)
|
|
200
|
-
let tiny = WasmF64.reinterpretI64(0x01A56E1FC2F8F359N)
|
|
201
|
-
let l1 = WasmF64.reinterpretI64(0x3FE3333333333303N)
|
|
202
|
-
let l2 = WasmF64.reinterpretI64(0x3FDB6DB6DB6FABFFN)
|
|
203
|
-
let l3 = WasmF64.reinterpretI64(0x3FD55555518F264DN)
|
|
204
|
-
let l4 = WasmF64.reinterpretI64(0x3FD17460A91D4101N)
|
|
205
|
-
let l5 = WasmF64.reinterpretI64(0x3FCD864A93C9DB65N)
|
|
206
|
-
let l6 = WasmF64.reinterpretI64(0x3FCA7E284A454EEFN)
|
|
207
|
-
let p1 = WasmF64.reinterpretI64(0x3FC555555555553EN)
|
|
208
|
-
let p2 = WasmF64.reinterpretI64(0xBF66C16C16BEBD93N)
|
|
209
|
-
let p3 = WasmF64.reinterpretI64(0x3F11566AAF25DE2CN)
|
|
210
|
-
let p4 = WasmF64.reinterpretI64(0xBEBBBD41C5D26BF1N)
|
|
211
|
-
let p5 = WasmF64.reinterpretI64(0x3E66376972BEA4D0N)
|
|
212
|
-
let lg2 = WasmF64.reinterpretI64(0x3FE62E42FEFA39EFN)
|
|
213
|
-
let lg2_h = WasmF64.reinterpretI64(0x3FE62E4300000000N)
|
|
214
|
-
let lg2_l = WasmF64.reinterpretI64(0xBE205C610CA86C39N)
|
|
215
|
-
let ovt = WasmF64.reinterpretI64(0x3C971547652B82FEN)
|
|
216
|
-
let cp = WasmF64.reinterpretI64(0x3FEEC709DC3A03FDN)
|
|
217
|
-
let cp_h = WasmF64.reinterpretI64(0x3FEEC709E0000000N)
|
|
218
|
-
let cp_l = WasmF64.reinterpretI64(0xBE3E2FE0145B01F5N)
|
|
219
|
-
let ivln2 = WasmF64.reinterpretI64(0x3FF71547652B82FEN)
|
|
220
|
-
let ivln2_h = WasmF64.reinterpretI64(0x3FF7154760000000N)
|
|
221
|
-
let ivln2_l = WasmF64.reinterpretI64(0x3E54AE0BF85DDF44N)
|
|
222
|
-
let inv3 = WasmF64.reinterpretI64(0x3FD5555555555555N)
|
|
223
|
-
let (==) = WasmI32.eq
|
|
224
|
-
let (!=) = WasmI32.ne
|
|
225
|
-
let (>=) = WasmI32.geS
|
|
226
|
-
let (<=) = WasmI32.leS
|
|
227
|
-
let (&) = WasmI32.and
|
|
228
|
-
let (|) = WasmI32.or
|
|
229
|
-
let (>) = WasmI32.gtS
|
|
230
|
-
let (<) = WasmI32.ltS
|
|
231
|
-
let (<<) = WasmI32.shl
|
|
232
|
-
let (>>) = WasmI32.shrS
|
|
233
|
-
let (-) = WasmI32.sub
|
|
234
|
-
let (+) = WasmI32.add
|
|
235
|
-
let u_ = WasmI64.reinterpretF64(x)
|
|
236
|
-
let hx = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
237
|
-
let lx = WasmI32.wrapI64(u_)
|
|
238
|
-
let u_ = WasmI64.reinterpretF64(y)
|
|
239
|
-
let hy = WasmI32.wrapI64(WasmI64.shrS(u_, 32N))
|
|
240
|
-
let ly = WasmI32.wrapI64(u_)
|
|
241
|
-
let mut ix = hx & 0x7FFFFFFFn
|
|
242
|
-
let iy = hy & 0x7FFFFFFFn
|
|
243
|
-
if ((iy | ly) == 0n) { // x**0 = 1, even if x is NaN
|
|
244
|
-
1 // return 1
|
|
245
|
-
} else if (
|
|
246
|
-
// Either Argument is Nan
|
|
247
|
-
ix > 0x7FF00000n ||
|
|
248
|
-
ix == 0x7FF00000n && lx != 0n ||
|
|
249
|
-
iy > 0x7FF00000n ||
|
|
250
|
-
iy == 0x7FF00000n && ly != 0n
|
|
251
|
-
) {
|
|
252
|
-
WasmI32.toGrain(newFloat64(WasmF64.add(x, y))): Number
|
|
253
|
-
} else {
|
|
254
|
-
let mut yisint = 0n
|
|
255
|
-
let mut k = 0n
|
|
256
|
-
if (hx < 0n) {
|
|
257
|
-
if (iy >= 0x43400000n) {
|
|
258
|
-
yisint = 2n
|
|
259
|
-
} else if (iy >= 0x3FF00000n) {
|
|
260
|
-
k = (iy >> 20n) - 0x3FFn
|
|
261
|
-
let mut offset = 0n
|
|
262
|
-
let mut _ly = 0n
|
|
263
|
-
if (k > 20n) {
|
|
264
|
-
offset = 52n - k
|
|
265
|
-
_ly = ly
|
|
266
|
-
} else {
|
|
267
|
-
offset = 20n - k
|
|
268
|
-
_ly = iy
|
|
269
|
-
}
|
|
270
|
-
let jj = _ly >> offset
|
|
271
|
-
if (jj << offset == _ly) yisint = 2n - (jj & 1n)
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (ly == 0n) {
|
|
275
|
-
if (iy == 0x7FF00000n) { // y is +- inf
|
|
276
|
-
foundOutput = true
|
|
277
|
-
if ((ix - 0x3FF00000n | lx) == 0n) { // C: (-1)**+-inf is 1, JS: NaN
|
|
278
|
-
output = nan
|
|
279
|
-
} else if (ix >= 0x3FF00000n) { // (|x|>1)**+-inf = inf,0
|
|
280
|
-
if (hy >= 0n) output = y else output = 0.0W
|
|
281
|
-
} else { // (|x|<1)**+-inf = 0,inf
|
|
282
|
-
if (hy >= 0n) output = 0.0W else output = y * -1.0W
|
|
283
|
-
}
|
|
284
|
-
} else if (iy == 0x3FF00000n) {
|
|
285
|
-
foundOutput = true
|
|
286
|
-
if (hy >= 0n) output = x else output = 1.0W / x
|
|
287
|
-
} else if (hy == 0x3FE00000n) {
|
|
288
|
-
foundOutput = true
|
|
289
|
-
output = x * x
|
|
290
|
-
} else if (hy == 0x3FE00000n) {
|
|
291
|
-
if (hx >= 0n) {
|
|
292
|
-
foundOutput = true
|
|
293
|
-
output = WasmF64.sqrt(x)
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
if (foundOutput) {
|
|
298
|
-
WasmI32.toGrain(newFloat64(output)): Number
|
|
299
|
-
} else {
|
|
300
|
-
let mut ax = WasmF64.abs(x)
|
|
301
|
-
let mut z = 0.0W
|
|
302
|
-
if (
|
|
303
|
-
lx == 0n && (ix == 0n || ix == 0x7FF00000n || ix == 0x3FF00000n)
|
|
304
|
-
) {
|
|
305
|
-
z = ax
|
|
306
|
-
if (hy < 0n) z = 1.0W / z
|
|
307
|
-
if (hx < 0n) {
|
|
308
|
-
if ((ix - 0x3FF00000n | yisint) == 0n) {
|
|
309
|
-
let d = WasmF64.sub(z, z)
|
|
310
|
-
z = d / d
|
|
311
|
-
} else if (yisint == 1n) z *= -1.0W
|
|
312
|
-
}
|
|
313
|
-
WasmI32.toGrain(newFloat64(z)): Number
|
|
314
|
-
} else {
|
|
315
|
-
let mut s = 1.0W
|
|
316
|
-
if (hx < 0n) {
|
|
317
|
-
if (yisint == 0n) {
|
|
318
|
-
let d = WasmF64.sub(x, x)
|
|
319
|
-
foundOutput = true
|
|
320
|
-
output = d / d
|
|
321
|
-
} else if (yisint == 1n) s = -1.0W
|
|
322
|
-
}
|
|
323
|
-
if (foundOutput) {
|
|
324
|
-
WasmI32.toGrain(newFloat64(output)): Number
|
|
325
|
-
} else {
|
|
326
|
-
let mut t1 = 0.0W,
|
|
327
|
-
t2 = 0.0W,
|
|
328
|
-
p_h = 0.0W,
|
|
329
|
-
p_l = 0.0W,
|
|
330
|
-
r = 0.0W,
|
|
331
|
-
t = 0.0W,
|
|
332
|
-
u = 0.0W,
|
|
333
|
-
v = 0.0W,
|
|
334
|
-
w = 0.0W
|
|
335
|
-
let mut j = 0n, n = 0n
|
|
336
|
-
if (iy > 0x41E00000n) {
|
|
337
|
-
if (iy > 0x43F00000n) {
|
|
338
|
-
if (ix <= 0x3FEFFFFFn) {
|
|
339
|
-
foundOutput = true
|
|
340
|
-
if (hy < 0n) output = huge * huge else output = tiny * tiny
|
|
341
|
-
} else if (ix >= 0x3FF00000n) {
|
|
342
|
-
foundOutput = true
|
|
343
|
-
if (hy > 0n) output = huge * huge else output = tiny * tiny
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
if (!foundOutput) {
|
|
347
|
-
if (ix < 0x3FEFFFFFn) {
|
|
348
|
-
foundOutput = true
|
|
349
|
-
if (hy < 0n) {
|
|
350
|
-
output = s * huge * huge
|
|
351
|
-
} else {
|
|
352
|
-
output = s * tiny * tiny
|
|
353
|
-
}
|
|
354
|
-
} else if (ix > 0x3FF00000n) {
|
|
355
|
-
foundOutput = true
|
|
356
|
-
if (hy > 0n) {
|
|
357
|
-
output = s * huge * huge
|
|
358
|
-
} else {
|
|
359
|
-
output = s * tiny * tiny
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
let (-) = WasmF64.sub
|
|
363
|
-
let (&) = WasmI64.and
|
|
364
|
-
t = ax - 1.0W
|
|
365
|
-
w = t * t * (0.5W - t * (inv3 - t * 0.25W))
|
|
366
|
-
u = ivln2_h * t
|
|
367
|
-
v = t * ivln2_l - w * ivln2
|
|
368
|
-
t1 = WasmF64.add(u, v)
|
|
369
|
-
t1 = WasmF64.reinterpretI64(
|
|
370
|
-
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
371
|
-
)
|
|
372
|
-
t2 = v - (t1 - u)
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
} else {
|
|
376
|
-
let mut ss = 0.0W,
|
|
377
|
-
s2 = 0.0W,
|
|
378
|
-
s_h = 0.0W,
|
|
379
|
-
s_l = 0.0W,
|
|
380
|
-
t_h = 0.0W,
|
|
381
|
-
t_l = 0.0W
|
|
382
|
-
n = 0n
|
|
383
|
-
if (ix < 0x00100000n) {
|
|
384
|
-
let (>>) = WasmI64.shrU
|
|
385
|
-
ax *= two53
|
|
386
|
-
n -= 53n
|
|
387
|
-
ix = WasmI32.wrapI64(WasmI64.reinterpretF64(ax) >> 32N)
|
|
388
|
-
}
|
|
389
|
-
n += (ix >> 20n) - 0x3FFn
|
|
390
|
-
j = ix & 0x000FFFFFn
|
|
391
|
-
ix = j | 0x3FF00000n
|
|
392
|
-
if (j <= 0x3988En) {
|
|
393
|
-
k = 0n
|
|
394
|
-
} else if (j < 0xBB67An) {
|
|
395
|
-
k = 1n
|
|
396
|
-
} else {
|
|
397
|
-
k = 0n
|
|
398
|
-
n += 1n
|
|
399
|
-
ix -= 0x00100000n
|
|
400
|
-
}
|
|
401
|
-
let (&) = WasmI64.and
|
|
402
|
-
let (|) = WasmI64.or
|
|
403
|
-
let (<<) = WasmI64.shl
|
|
404
|
-
ax = WasmF64.reinterpretI64(
|
|
405
|
-
WasmI64.reinterpretF64(ax) & 0xFFFFFFFFN |
|
|
406
|
-
WasmI64.extendI32S(ix) << 32N
|
|
407
|
-
)
|
|
408
|
-
let bp = if (k != 0n) 1.5W else 1.0W
|
|
409
|
-
u = WasmF64.sub(ax, bp)
|
|
410
|
-
v = 1.0W / WasmF64.add(ax, bp)
|
|
411
|
-
ss = u * v
|
|
412
|
-
s_h = ss
|
|
413
|
-
s_h = WasmF64.reinterpretI64(
|
|
414
|
-
WasmI64.reinterpretF64(s_h) & 0xFFFFFFFF00000000N
|
|
415
|
-
)
|
|
416
|
-
t_h = WasmF64.reinterpretI64(
|
|
417
|
-
WasmI64.shl(
|
|
418
|
-
WasmI64.extendI32S(
|
|
419
|
-
WasmI32.or(WasmI32.shrS(ix, 1n), 0x20000000n) +
|
|
420
|
-
0x00080000n +
|
|
421
|
-
WasmI32.shl(k, 18n)
|
|
422
|
-
),
|
|
423
|
-
32N
|
|
424
|
-
)
|
|
425
|
-
)
|
|
426
|
-
let (-) = WasmF64.sub
|
|
427
|
-
let (+) = WasmF64.add
|
|
428
|
-
t_l = ax - (t_h - bp)
|
|
429
|
-
s_l = v * (u - s_h * t_h - s_h * t_l)
|
|
430
|
-
s2 = ss * ss
|
|
431
|
-
//formatter-ignore
|
|
432
|
-
r = s2 * s2 * (l1 + s2 * (l2 + s2 * (l3 + s2 * (l4 + s2 * (l5 + s2 * l6)))))
|
|
433
|
-
r += s_l * (s_h + ss)
|
|
434
|
-
s2 = s_h * s_h
|
|
435
|
-
t_h = 3.0W + s2 + r
|
|
436
|
-
t_h = WasmF64.reinterpretI64(
|
|
437
|
-
WasmI64.reinterpretF64(t_h) & 0xFFFFFFFF00000000N
|
|
438
|
-
)
|
|
439
|
-
t_l = r - (t_h - 3.0W - s2)
|
|
440
|
-
u = s_h * t_h
|
|
441
|
-
v = s_l * t_h + t_l * ss
|
|
442
|
-
p_h = u + v
|
|
443
|
-
p_h = WasmF64.reinterpretI64(
|
|
444
|
-
WasmI64.reinterpretF64(p_h) & 0xFFFFFFFF00000000N
|
|
445
|
-
)
|
|
446
|
-
p_l = v - (p_h - u)
|
|
447
|
-
let z_h = cp_h * p_h
|
|
448
|
-
let dp_l = if (k != 0n) dp_l1 else 0.0W
|
|
449
|
-
let z_l = cp_l * p_h + p_l * cp + dp_l
|
|
450
|
-
t = WasmF64.convertI32S(n)
|
|
451
|
-
let dp_h = if (k != 0n) dp_h1 else 0.0W
|
|
452
|
-
t1 = z_h + z_l + dp_h + t
|
|
453
|
-
t1 = WasmF64.reinterpretI64(
|
|
454
|
-
WasmI64.reinterpretF64(t1) & 0xFFFFFFFF00000000N
|
|
455
|
-
)
|
|
456
|
-
t2 = z_l - (t1 - t - dp_h - z_h)
|
|
457
|
-
}
|
|
458
|
-
if (foundOutput) {
|
|
459
|
-
WasmI32.toGrain(newFloat64(output)): Number
|
|
460
|
-
} else {
|
|
461
|
-
let (>) = WasmF64.gt
|
|
462
|
-
let (&) = WasmI64.and
|
|
463
|
-
let (-) = WasmF64.sub
|
|
464
|
-
let (+) = WasmF64.add
|
|
465
|
-
let (>>) = WasmI64.shrS
|
|
466
|
-
let y1 = WasmF64.reinterpretI64(
|
|
467
|
-
WasmI64.reinterpretF64(y) & 0xFFFFFFFF00000000N
|
|
468
|
-
)
|
|
469
|
-
p_l = (y - y1) * t1 + y * t2
|
|
470
|
-
p_h = y1 * t1
|
|
471
|
-
z = p_l + p_h
|
|
472
|
-
let u_ = WasmI64.reinterpretF64(z)
|
|
473
|
-
let j = WasmI32.wrapI64(u_ >> 32N)
|
|
474
|
-
let i = WasmI32.wrapI64(u_)
|
|
475
|
-
if (j >= 0x40900000n) {
|
|
476
|
-
if ((WasmI32.sub(j, 0x40900000n) | i) != 0n) {
|
|
477
|
-
foundOutput = true
|
|
478
|
-
output = s * huge * huge
|
|
479
|
-
} else if (p_l + ovt > z - p_h) {
|
|
480
|
-
foundOutput = true
|
|
481
|
-
output = s * huge * huge
|
|
482
|
-
}
|
|
483
|
-
} else if (WasmI32.and(j, 0x7FFFFFFFn) >= 0x4090CC00n) {
|
|
484
|
-
if (WasmI32.sub(j, 0xC090CC00n | i) != 0n) {
|
|
485
|
-
foundOutput = true
|
|
486
|
-
output = s * tiny * tiny
|
|
487
|
-
} else if (WasmF64.le(p_l, z - p_h)) {
|
|
488
|
-
foundOutput = true
|
|
489
|
-
output = s * tiny * tiny
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
if (foundOutput) {
|
|
493
|
-
WasmI32.toGrain(newFloat64(output)): Number
|
|
494
|
-
} else {
|
|
495
|
-
let (&) = WasmI32.and
|
|
496
|
-
let (>>) = WasmI32.shrS
|
|
497
|
-
let (-) = WasmI32.sub
|
|
498
|
-
let (+) = WasmI32.add
|
|
499
|
-
let (>) = WasmI32.gtS
|
|
500
|
-
let (*) = WasmI32.mul
|
|
501
|
-
let i = j & 0x7FFFFFFFn
|
|
502
|
-
k = (i >> 20n) - 0x3FFn
|
|
503
|
-
n = 0n
|
|
504
|
-
if (i > 0x3FE00000n) {
|
|
505
|
-
n = j + (0x00100000n >> k + 1n)
|
|
506
|
-
k = ((n & 0x7FFFFFFFn) >> 20n) - 0x3FFn
|
|
507
|
-
t = 0.0W
|
|
508
|
-
t = WasmF64.reinterpretI64(
|
|
509
|
-
WasmI64.shl(
|
|
510
|
-
WasmI64.extendI32S(
|
|
511
|
-
n & WasmI32.xor(0x000FFFFFn >> k, -1n)
|
|
512
|
-
),
|
|
513
|
-
32N
|
|
514
|
-
)
|
|
515
|
-
)
|
|
516
|
-
n = (n & 0x000FFFFFn | 0x00100000n) >> 20n - k
|
|
517
|
-
if (j < 0n) n *= -1n
|
|
518
|
-
p_h = WasmF64.sub(p_h, t)
|
|
519
|
-
}
|
|
520
|
-
let (&) = WasmI64.and
|
|
521
|
-
let (|) = WasmI64.or
|
|
522
|
-
let (*) = WasmF64.mul
|
|
523
|
-
let (-) = WasmF64.sub
|
|
524
|
-
let (+) = WasmF64.add
|
|
525
|
-
t = WasmF64.add(p_l, p_h)
|
|
526
|
-
t = WasmF64.reinterpretI64(
|
|
527
|
-
WasmI64.reinterpretF64(t) & 0xFFFFFFFF00000000N
|
|
528
|
-
)
|
|
529
|
-
u = t * lg2_h
|
|
530
|
-
v = (p_l - (t - p_h)) * lg2 + t * lg2_l
|
|
531
|
-
z = u + v
|
|
532
|
-
w = v - (z - u)
|
|
533
|
-
t = z * z
|
|
534
|
-
t1 = z - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5))))
|
|
535
|
-
r = z * t1 / (t1 - 2.0W) - (w + z * w)
|
|
536
|
-
z = 1.0W - (r - z)
|
|
537
|
-
let j = WasmI32.add(
|
|
538
|
-
WasmI32.wrapI64(
|
|
539
|
-
WasmI64.shrS(WasmI64.reinterpretF64(z), 32N)
|
|
540
|
-
),
|
|
541
|
-
WasmI32.shl(n, 20n)
|
|
542
|
-
)
|
|
543
|
-
if (WasmI32.shrS(j, 20n) <= 0n) {
|
|
544
|
-
z = scalbn(z, n)
|
|
545
|
-
} else {
|
|
546
|
-
z = WasmF64.reinterpretI64(
|
|
547
|
-
WasmI64.reinterpretF64(z) & 0xFFFFFFFFN |
|
|
548
|
-
WasmI64.shl(WasmI64.extendI32S(j), 32N)
|
|
549
|
-
)
|
|
550
|
-
}
|
|
551
|
-
WasmI32.toGrain(newFloat64(s * z)): Number
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
154
|
+
provide let (**) = (**)
|
|
561
155
|
|
|
562
156
|
/**
|
|
563
157
|
* Computes the exponentiation of Euler's number to the given power.
|
|
@@ -565,25 +159,32 @@ export let pow = (base, power) => {
|
|
|
565
159
|
* @param power: The exponent number
|
|
566
160
|
* @returns The `Number.e` value raised to the given power
|
|
567
161
|
*
|
|
162
|
+
* @example Number.exp(1) == Number.e
|
|
163
|
+
* @example Number.exp(10) == 22026.465794806703
|
|
164
|
+
*
|
|
568
165
|
* @since v0.5.4
|
|
569
166
|
*/
|
|
570
|
-
|
|
571
|
-
if (power == 0) 1 else
|
|
167
|
+
provide let exp = power => {
|
|
168
|
+
if (power == 0) 1 else e ** power
|
|
572
169
|
}
|
|
170
|
+
|
|
573
171
|
/**
|
|
574
172
|
* Computes the square root of its operand.
|
|
575
173
|
*
|
|
576
174
|
* @param x: The number to square root
|
|
577
175
|
* @returns The square root of the operand
|
|
578
176
|
*
|
|
177
|
+
* @example Number.sqrt(25) == 5
|
|
178
|
+
*
|
|
579
179
|
* @since v0.4.0
|
|
580
180
|
*/
|
|
581
181
|
@unsafe
|
|
582
|
-
|
|
182
|
+
provide let sqrt = (x: Number) => {
|
|
183
|
+
use WasmF64.{ (==) }
|
|
583
184
|
let xval = coerceNumberToWasmF64(x)
|
|
584
185
|
let x = WasmI32.fromGrain(x)
|
|
585
186
|
let sqrtd = WasmF64.sqrt(xval)
|
|
586
|
-
if (!isFloat(x) &&
|
|
187
|
+
if (!isFloat(x) && sqrtd == WasmF64.trunc(sqrtd)) {
|
|
587
188
|
WasmI32.toGrain(reducedInteger(WasmI64.truncF64S(sqrtd))): Number
|
|
588
189
|
} else {
|
|
589
190
|
WasmI32.toGrain(newFloat64(sqrtd)): Number
|
|
@@ -599,8 +200,10 @@ export let sqrt = (x: Number) => {
|
|
|
599
200
|
* @example Number.sign(-10000) == -1
|
|
600
201
|
* @example Number.sign(222222) == 1
|
|
601
202
|
* @example Number.sign(0) == 0
|
|
203
|
+
*
|
|
204
|
+
* @since v0.5.0
|
|
602
205
|
*/
|
|
603
|
-
|
|
206
|
+
provide let sign = x => {
|
|
604
207
|
match (x) {
|
|
605
208
|
x when x < 0 => -1,
|
|
606
209
|
x when x > 0 => 1,
|
|
@@ -615,10 +218,12 @@ export let sign = x => {
|
|
|
615
218
|
* @param y: The second operand
|
|
616
219
|
* @returns The smaller of the two operands
|
|
617
220
|
*
|
|
221
|
+
* @example Number.min(5, 2) == 2
|
|
222
|
+
*
|
|
618
223
|
* @since v0.4.0
|
|
619
224
|
* @history v0.5.4: Handle NaN properly
|
|
620
225
|
*/
|
|
621
|
-
|
|
226
|
+
provide let min = (x: Number, y: Number) => if (compare(x, y) < 0) x else y
|
|
622
227
|
|
|
623
228
|
/**
|
|
624
229
|
* Returns the larger of its operands.
|
|
@@ -627,10 +232,12 @@ export let min = (x: Number, y: Number) => if (compare(x, y) < 0) x else y
|
|
|
627
232
|
* @param y: The second operand
|
|
628
233
|
* @returns The larger of the two operands
|
|
629
234
|
*
|
|
235
|
+
* @example Number.max(5, 2) == 5
|
|
236
|
+
*
|
|
630
237
|
* @since v0.4.0
|
|
631
238
|
* @history v0.5.4: Handle NaN properly
|
|
632
239
|
*/
|
|
633
|
-
|
|
240
|
+
provide let max = (x: Number, y: Number) => if (compare(x, y) > 0) x else y
|
|
634
241
|
|
|
635
242
|
/**
|
|
636
243
|
* Rounds its operand up to the next largest integer.
|
|
@@ -638,15 +245,18 @@ export let max = (x: Number, y: Number) => if (compare(x, y) > 0) x else y
|
|
|
638
245
|
* @param x: The number to round
|
|
639
246
|
* @returns The next largest integer of the operand
|
|
640
247
|
*
|
|
248
|
+
* @example Number.ceil(5.5) == 6
|
|
249
|
+
* @example Number.ceil(-5.5) == -5
|
|
250
|
+
*
|
|
641
251
|
* @since v0.4.0
|
|
642
252
|
* @history v0.5.4: Handle NaN and Infinity properly
|
|
643
253
|
*/
|
|
644
254
|
@unsafe
|
|
645
|
-
|
|
255
|
+
provide let ceil = (x: Number) => {
|
|
646
256
|
if (x != x) {
|
|
647
|
-
|
|
648
|
-
} else if (x ==
|
|
649
|
-
|
|
257
|
+
NaN
|
|
258
|
+
} else if (x == Infinity) {
|
|
259
|
+
Infinity
|
|
650
260
|
} else {
|
|
651
261
|
let xval = coerceNumberToWasmF64(x)
|
|
652
262
|
let ceiling = WasmI64.truncF64S(WasmF64.ceil(xval))
|
|
@@ -660,15 +270,18 @@ export let ceil = (x: Number) => {
|
|
|
660
270
|
* @param x: The number to round
|
|
661
271
|
* @returns The previous integer of the operand
|
|
662
272
|
*
|
|
273
|
+
* @example Number.floor(5.5) == 5
|
|
274
|
+
* @example Number.floor(-5.5) == -6
|
|
275
|
+
*
|
|
663
276
|
* @since v0.4.0
|
|
664
277
|
* @history v0.5.4: Handle NaN and Infinity properly
|
|
665
278
|
*/
|
|
666
279
|
@unsafe
|
|
667
|
-
|
|
280
|
+
provide let floor = (x: Number) => {
|
|
668
281
|
if (x != x) {
|
|
669
|
-
|
|
670
|
-
} else if (x ==
|
|
671
|
-
|
|
282
|
+
NaN
|
|
283
|
+
} else if (x == Infinity) {
|
|
284
|
+
Infinity
|
|
672
285
|
} else {
|
|
673
286
|
let xval = coerceNumberToWasmF64(x)
|
|
674
287
|
let floored = WasmI64.truncF64S(WasmF64.floor(xval))
|
|
@@ -682,15 +295,17 @@ export let floor = (x: Number) => {
|
|
|
682
295
|
* @param x: The number to truncate
|
|
683
296
|
* @returns The integer part of the operand
|
|
684
297
|
*
|
|
298
|
+
* @example Number.trunc(5.5) == 5
|
|
299
|
+
*
|
|
685
300
|
* @since v0.4.0
|
|
686
301
|
* @history v0.5.4: Handle NaN and Infinity properly
|
|
687
302
|
*/
|
|
688
303
|
@unsafe
|
|
689
|
-
|
|
304
|
+
provide let trunc = (x: Number) => {
|
|
690
305
|
if (x != x) {
|
|
691
|
-
|
|
692
|
-
} else if (x ==
|
|
693
|
-
|
|
306
|
+
NaN
|
|
307
|
+
} else if (x == Infinity) {
|
|
308
|
+
Infinity
|
|
694
309
|
} else {
|
|
695
310
|
let xval = coerceNumberToWasmF64(x)
|
|
696
311
|
let trunced = WasmI64.truncF64S(xval)
|
|
@@ -704,15 +319,20 @@ export let trunc = (x: Number) => {
|
|
|
704
319
|
* @param x: The number to round
|
|
705
320
|
* @returns The nearest integer to the operand
|
|
706
321
|
*
|
|
322
|
+
* @example Number.round(5.5) == 6
|
|
323
|
+
* @example Number.round(5.4) == 5
|
|
324
|
+
* @example Number.round(-5.5) == -6
|
|
325
|
+
* @example Number.round(-5.4) == -5
|
|
326
|
+
*
|
|
707
327
|
* @since v0.4.0
|
|
708
328
|
* @history v0.5.4: Handle NaN and Infinity properly
|
|
709
329
|
*/
|
|
710
330
|
@unsafe
|
|
711
|
-
|
|
331
|
+
provide let round = (x: Number) => {
|
|
712
332
|
if (x != x) {
|
|
713
|
-
|
|
714
|
-
} else if (x ==
|
|
715
|
-
|
|
333
|
+
NaN
|
|
334
|
+
} else if (x == Infinity) {
|
|
335
|
+
Infinity
|
|
716
336
|
} else {
|
|
717
337
|
let xval = coerceNumberToWasmF64(x)
|
|
718
338
|
let rounded = WasmI64.truncF64S(WasmF64.nearest(xval))
|
|
@@ -726,9 +346,12 @@ export let round = (x: Number) => {
|
|
|
726
346
|
* @param x: The operand
|
|
727
347
|
* @returns The absolute value of the operand
|
|
728
348
|
*
|
|
349
|
+
* @example Number.abs(-1) == 1
|
|
350
|
+
* @example Number.abs(5) == 5
|
|
351
|
+
*
|
|
729
352
|
* @since v0.4.0
|
|
730
353
|
*/
|
|
731
|
-
|
|
354
|
+
provide let abs = (x: Number) => if (0 > x) x * -1 else x
|
|
732
355
|
|
|
733
356
|
/**
|
|
734
357
|
* Returns the negation of its operand.
|
|
@@ -736,9 +359,12 @@ export let abs = (x: Number) => if (0 > x) x * -1 else x
|
|
|
736
359
|
* @param x: The number to negate
|
|
737
360
|
* @returns The negated operand
|
|
738
361
|
*
|
|
362
|
+
* @example Number.neg(-1) == 1
|
|
363
|
+
* @example Number.neg(1) == -1
|
|
364
|
+
*
|
|
739
365
|
* @since v0.4.0
|
|
740
366
|
*/
|
|
741
|
-
|
|
367
|
+
provide let neg = (x: Number) => x * -1
|
|
742
368
|
|
|
743
369
|
/**
|
|
744
370
|
* Checks if a number is a floating point value.
|
|
@@ -746,10 +372,17 @@ export let neg = (x: Number) => x * -1
|
|
|
746
372
|
* @param x: The number to check
|
|
747
373
|
* @returns `true` if the value is a floating point number or `false` otherwise
|
|
748
374
|
*
|
|
375
|
+
* @example Number.isFloat(0.5)
|
|
376
|
+
* @example Number.isFloat(1.0)
|
|
377
|
+
* @example Number.isFloat(Infinity)
|
|
378
|
+
* @example Number.isFloat(NaN)
|
|
379
|
+
* @example Number.isFloat(1/2) == false
|
|
380
|
+
* @example Number.isFloat(1) == false
|
|
381
|
+
*
|
|
749
382
|
* @since v0.5.3
|
|
750
383
|
*/
|
|
751
384
|
@unsafe
|
|
752
|
-
|
|
385
|
+
provide let isFloat = (x: Number) => {
|
|
753
386
|
isFloat(WasmI32.fromGrain(x))
|
|
754
387
|
}
|
|
755
388
|
|
|
@@ -759,10 +392,17 @@ export let isFloat = (x: Number) => {
|
|
|
759
392
|
* @param x: The number to check
|
|
760
393
|
* @returns `true` if the value is an integer or `false` otherwise
|
|
761
394
|
*
|
|
395
|
+
* @example Number.isInteger(1)
|
|
396
|
+
* @example Number.isInteger(0.5) == false
|
|
397
|
+
* @example Number.isInteger(1.0) == false
|
|
398
|
+
* @example Number.isInteger(1/2) == false
|
|
399
|
+
* @example Number.isInteger(Infinity) == false
|
|
400
|
+
* @example Number.isInteger(NaN) == false
|
|
401
|
+
*
|
|
762
402
|
* @since v0.5.3
|
|
763
403
|
*/
|
|
764
404
|
@unsafe
|
|
765
|
-
|
|
405
|
+
provide let isInteger = (x: Number) => {
|
|
766
406
|
isInteger(WasmI32.fromGrain(x))
|
|
767
407
|
}
|
|
768
408
|
|
|
@@ -772,10 +412,17 @@ export let isInteger = (x: Number) => {
|
|
|
772
412
|
* @param x: The number to check
|
|
773
413
|
* @returns `true` if the value is a non-integer rational number or `false` otherwise
|
|
774
414
|
*
|
|
415
|
+
* @example Number.isRational(1/2)
|
|
416
|
+
* @example Number.isRational(0.5) == false
|
|
417
|
+
* @example Number.isRational(1.0) == false
|
|
418
|
+
* @example Number.isRational(1) == false
|
|
419
|
+
* @example Number.isRational(Infinity) == false
|
|
420
|
+
* @example Number.isRational(NaN) == false
|
|
421
|
+
*
|
|
775
422
|
* @since v0.5.3
|
|
776
423
|
*/
|
|
777
424
|
@unsafe
|
|
778
|
-
|
|
425
|
+
provide let isRational = (x: Number) => {
|
|
779
426
|
isRational(WasmI32.fromGrain(x))
|
|
780
427
|
}
|
|
781
428
|
|
|
@@ -786,23 +433,30 @@ export let isRational = (x: Number) => {
|
|
|
786
433
|
* @param x: The number to check
|
|
787
434
|
* @returns `true` if the value is finite or `false` otherwise
|
|
788
435
|
*
|
|
436
|
+
* @example Number.isFinite(1/2)
|
|
437
|
+
* @example Number.isFinite(0.5)
|
|
438
|
+
* @example Number.isFinite(1.0)
|
|
439
|
+
* @example Number.isFinite(1)
|
|
440
|
+
* @example Number.isFinite(Infinity) == false
|
|
441
|
+
* @example Number.isFinite(-Infinity) == false
|
|
442
|
+
* @example Number.isFinite(NaN) == false
|
|
443
|
+
*
|
|
789
444
|
* @since v0.4.0
|
|
790
445
|
*/
|
|
791
446
|
@unsafe
|
|
792
|
-
|
|
447
|
+
provide let isFinite = (x: Number) => {
|
|
448
|
+
use WasmI32.{ (==) }
|
|
793
449
|
let asPtr = WasmI32.fromGrain(x)
|
|
794
450
|
if (isBoxedNumber(asPtr)) {
|
|
795
451
|
// Boxed numbers can have multiple subtypes, of which float32 and float64 can be infinite.
|
|
796
452
|
let tag = WasmI32.load(asPtr, 4n)
|
|
797
|
-
if (
|
|
453
|
+
if (tag == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) {
|
|
454
|
+
use WasmF64.{ (-), (==) }
|
|
798
455
|
// uses the fact that all finite floats minus themselves are zero
|
|
799
456
|
// (NaN - NaN == NaN, inf - inf == NaN,
|
|
800
457
|
// -inf - -inf == NaN, inf - -inf == inf, -inf - inf == -inf)
|
|
801
458
|
let wf64 = WasmF64.load(asPtr, 8n)
|
|
802
|
-
|
|
803
|
-
} else if (WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)) {
|
|
804
|
-
let wf32 = WasmF32.load(asPtr, 8n)
|
|
805
|
-
WasmF32.eq(WasmF32.sub(wf32, wf32), 0.w)
|
|
459
|
+
wf64 - wf64 == 0.0W
|
|
806
460
|
} else {
|
|
807
461
|
// Neither rational numbers nor boxed integers can be infinite or NaN.
|
|
808
462
|
// Grain doesn't allow creating a rational with denominator of zero either.
|
|
@@ -820,10 +474,18 @@ export let isFinite = (x: Number) => {
|
|
|
820
474
|
* @param x: The number to check
|
|
821
475
|
* @returns `true` if the value is NaN, otherwise `false`
|
|
822
476
|
*
|
|
477
|
+
* @example Number.isNaN(NaN)
|
|
478
|
+
* @example Number.isNaN(Infinity) == false
|
|
479
|
+
* @example Number.isNaN(-Infinity) == false
|
|
480
|
+
* @example Number.isNaN(1/2) == false
|
|
481
|
+
* @example Number.isNaN(0.5) == false
|
|
482
|
+
* @example Number.isNaN(1.0) == false
|
|
483
|
+
* @example Number.isNaN(1) == false
|
|
484
|
+
*
|
|
823
485
|
* @since v0.4.0
|
|
824
486
|
*/
|
|
825
487
|
@unsafe
|
|
826
|
-
|
|
488
|
+
provide let isNaN = (x: Number) => {
|
|
827
489
|
let asPtr = WasmI32.fromGrain(x)
|
|
828
490
|
isNaN(asPtr)
|
|
829
491
|
}
|
|
@@ -835,21 +497,28 @@ export let isNaN = (x: Number) => {
|
|
|
835
497
|
* @param x: The number to check
|
|
836
498
|
* @returns `true` if the value is infinite or `false` otherwise
|
|
837
499
|
*
|
|
500
|
+
* @example Number.isInfinite(Infinity)
|
|
501
|
+
* @example Number.isInfinite(-Infinity)
|
|
502
|
+
* @example Number.isInfinite(NaN) == false
|
|
503
|
+
* @example Number.isInfinite(1/2) == false
|
|
504
|
+
* @example Number.isInfinite(0.5) == false
|
|
505
|
+
* @example Number.isInfinite(1.0) == false
|
|
506
|
+
* @example Number.isInfinite(1) == false
|
|
507
|
+
*
|
|
838
508
|
* @since v0.4.0
|
|
839
509
|
*/
|
|
840
510
|
@unsafe
|
|
841
|
-
|
|
511
|
+
provide let isInfinite = (x: Number) => {
|
|
512
|
+
use WasmI32.{ (==) }
|
|
842
513
|
// The following code is equivalent to (!isFinite(x) && !isNaN(x)),
|
|
843
514
|
// so see those functions to understand what's going on here.
|
|
844
515
|
let asPtr = WasmI32.fromGrain(x)
|
|
845
516
|
if (isBoxedNumber(asPtr)) {
|
|
846
517
|
let tag = WasmI32.load(asPtr, 4n)
|
|
847
|
-
if (
|
|
518
|
+
if (tag == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) {
|
|
519
|
+
use WasmF64.{ (-), (==), (!=) }
|
|
848
520
|
let wf64 = WasmF64.load(asPtr, 8n)
|
|
849
|
-
|
|
850
|
-
} else if (WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)) {
|
|
851
|
-
let wf32 = WasmF32.load(asPtr, 8n)
|
|
852
|
-
WasmF32.ne(WasmF32.sub(wf32, wf32), 0.w) && WasmF32.eq(wf32, wf32)
|
|
521
|
+
wf64 - wf64 != 0.0W && wf64 == wf64
|
|
853
522
|
} else {
|
|
854
523
|
false
|
|
855
524
|
}
|
|
@@ -858,6 +527,38 @@ export let isInfinite = (x: Number) => {
|
|
|
858
527
|
}
|
|
859
528
|
}
|
|
860
529
|
|
|
530
|
+
/**
|
|
531
|
+
* Determines whether two values are considered close to each other using a relative and absolute tolerance.
|
|
532
|
+
*
|
|
533
|
+
* @param a: The first value
|
|
534
|
+
* @param b: The second value
|
|
535
|
+
* @param relativeTolerance: The maximum tolerance to use relative to the larger absolute value `a` or `b`
|
|
536
|
+
* @param absoluteTolerance: The absolute tolerance to use, regardless of the values of `a` or `b`
|
|
537
|
+
* @returns `true` if the values are considered close to each other or `false` otherwise
|
|
538
|
+
*
|
|
539
|
+
* @example Number.isClose(1.233, 1.233)
|
|
540
|
+
* @example Number.isClose(1.233, 1.233000001)
|
|
541
|
+
* @example Number.isClose(8.005, 8.450, absoluteTolerance=0.5)
|
|
542
|
+
* @example Number.isClose(4, 4.1, relativeTolerance=0.025)
|
|
543
|
+
* @example Number.isClose(1.233, 1.24) == false
|
|
544
|
+
* @example Number.isClose(1.233, 1.4566) == false
|
|
545
|
+
* @example Number.isClose(8.005, 8.450, absoluteTolerance=0.4) == false
|
|
546
|
+
* @example Number.isClose(4, 4.1, relativeTolerance=0.024) == false
|
|
547
|
+
*
|
|
548
|
+
* @since v0.6.0
|
|
549
|
+
*/
|
|
550
|
+
provide let isClose = (a, b, relativeTolerance=1e-9, absoluteTolerance=0.0) => {
|
|
551
|
+
if (a == b) {
|
|
552
|
+
true
|
|
553
|
+
} else if (isFinite(a) && isFinite(b)) {
|
|
554
|
+
abs(a - b) <=
|
|
555
|
+
max(relativeTolerance * max(abs(a), abs(b)), absoluteTolerance)
|
|
556
|
+
} else {
|
|
557
|
+
// NaN and infinities which were not equal
|
|
558
|
+
false
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
861
562
|
/**
|
|
862
563
|
* Parses a string representation of an integer into a `Number` using the
|
|
863
564
|
* specified radix (also known as a number system "base").
|
|
@@ -867,24 +568,33 @@ export let isInfinite = (x: Number) => {
|
|
|
867
568
|
* favor of the prefix. Underscores that appear in the numeric portion of the
|
|
868
569
|
* input are ignored.
|
|
869
570
|
*
|
|
870
|
-
* @param
|
|
571
|
+
* @param string: The string to parse
|
|
871
572
|
* @param radix: The number system base to use when parsing the input string
|
|
872
|
-
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(
|
|
573
|
+
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(err)` containing a variant of `ParseIntError`
|
|
574
|
+
*
|
|
575
|
+
* @example Number.parseInt("1", radix=10) == Ok(1)
|
|
576
|
+
* @example Number.parseInt("-1", radix=10) == Ok(-1)
|
|
577
|
+
* @example Number.parseInt("0xf0", radix=16) == Ok(0x0f0)
|
|
873
578
|
*
|
|
874
579
|
* @since v0.4.5
|
|
580
|
+
* @history v0.6.0: Switched from a string-based error message to a structured error enum
|
|
875
581
|
*/
|
|
876
|
-
|
|
582
|
+
provide let parseInt = Atoi.parseInt
|
|
877
583
|
|
|
878
584
|
/**
|
|
879
585
|
* Parses a string representation of a float into a `Number`. Underscores that appear
|
|
880
586
|
* in numeric portions of the input are ignored.
|
|
881
587
|
*
|
|
882
|
-
* @param
|
|
588
|
+
* @param string: The string to parse
|
|
883
589
|
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
|
|
884
590
|
*
|
|
591
|
+
* @example Number.parseFloat("1") == Ok(1.0)
|
|
592
|
+
* @example Number.parseFloat("-1") == Ok(-1.0)
|
|
593
|
+
* @example Number.parseFloat("-1.5") == Ok(-1.5)
|
|
594
|
+
*
|
|
885
595
|
* @since v0.5.5
|
|
886
596
|
*/
|
|
887
|
-
|
|
597
|
+
provide let parseFloat = Atof.parseFloat
|
|
888
598
|
|
|
889
599
|
/**
|
|
890
600
|
* Parses a string representation of an integer, float, or rational into a `Number`.
|
|
@@ -893,58 +603,59 @@ export let parseFloat = Atof.parseFloat
|
|
|
893
603
|
* @param input: The string to parse
|
|
894
604
|
* @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
|
|
895
605
|
*
|
|
606
|
+
* @example Number.parse("1") == Ok(1)
|
|
607
|
+
* @example Number.parse("-1") == Ok(-1)
|
|
608
|
+
* @example Number.parse("0xf0") == Ok(0x0f0)
|
|
609
|
+
* @example Number.parse("-1.5") == Ok(-1.5)
|
|
610
|
+
*
|
|
896
611
|
* @since v0.5.5
|
|
897
612
|
*/
|
|
898
613
|
@unsafe
|
|
899
|
-
|
|
614
|
+
provide let parse = input => {
|
|
900
615
|
match (parseInt(input, 10)) {
|
|
901
616
|
Ok(number) => Ok(number),
|
|
902
|
-
Err(msg) =>
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
let (+) = WasmI32.add
|
|
908
|
-
let (-) = WasmI32.sub
|
|
909
|
-
let (<) = WasmI32.ltU
|
|
910
|
-
let (==) = WasmI32.eq
|
|
617
|
+
Err(msg) => match (parseFloat(input)) {
|
|
618
|
+
Ok(number) => Ok(number),
|
|
619
|
+
Err(_) => {
|
|
620
|
+
// Split the input on a `/` and attempt to parse a rational
|
|
621
|
+
use WasmI32.{ (+), (-), ltU as (<), (==) }
|
|
911
622
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
}
|
|
623
|
+
// Search for `/`
|
|
624
|
+
let input = WasmI32.fromGrain(input)
|
|
625
|
+
let len = WasmI32.load(input, 4n)
|
|
626
|
+
let mut slashIdx = -1n
|
|
627
|
+
for (let mut i = 0n; i < len; i += 1n) {
|
|
628
|
+
if (WasmI32.load8U(input + i, 8n) == 0x2fn) {
|
|
629
|
+
slashIdx = i
|
|
630
|
+
break
|
|
921
631
|
}
|
|
632
|
+
}
|
|
922
633
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
634
|
+
if (slashIdx == -1n) {
|
|
635
|
+
Err(msg)
|
|
636
|
+
} else {
|
|
637
|
+
let numeratorLen = slashIdx
|
|
638
|
+
let denominatorLen = len - slashIdx - 1n
|
|
928
639
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
640
|
+
let numerator = allocateString(numeratorLen)
|
|
641
|
+
Memory.copy(numerator + 8n, input + 8n, numeratorLen)
|
|
642
|
+
let numerator = WasmI32.toGrain(numerator): String
|
|
932
643
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
644
|
+
let denominator = allocateString(denominatorLen)
|
|
645
|
+
Memory.copy(
|
|
646
|
+
denominator + 8n,
|
|
647
|
+
input + 8n + slashIdx + 1n,
|
|
648
|
+
denominatorLen
|
|
649
|
+
)
|
|
650
|
+
let denominator = WasmI32.toGrain(denominator): String
|
|
940
651
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
}
|
|
652
|
+
match ((parseInt(numerator, 10), parseInt(denominator, 10))) {
|
|
653
|
+
(Ok(numerator), Ok(denominator)) => Ok(numerator / denominator),
|
|
654
|
+
(Err(msg), _) | (_, Err(msg)) => Err(msg),
|
|
945
655
|
}
|
|
946
|
-
}
|
|
656
|
+
}
|
|
947
657
|
},
|
|
658
|
+
},
|
|
948
659
|
}
|
|
949
660
|
}
|
|
950
661
|
|
|
@@ -970,136 +681,283 @@ let chebyshevSine = (radians: Number) => {
|
|
|
970
681
|
(radians - pi - pi_minor) * (radians + pi + pi_minor) * p1 * radians
|
|
971
682
|
}
|
|
972
683
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
*/
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
}
|
|
684
|
+
@unsafe
|
|
685
|
+
let rf = z => {
|
|
686
|
+
// see: musl/src/math/asin.c and SUN COPYRIGHT NOTICE at top of file
|
|
687
|
+
// Operators
|
|
688
|
+
use WasmF64.{ (+), (*), (/) }
|
|
689
|
+
/* coefficients for R(x^2) */
|
|
690
|
+
let pS0 = 1.66666666666666657415e-01W /* 0x3FC55555, 0x55555555 */
|
|
691
|
+
let pS1 = -3.25565818622400915405e-01W /* 0xBFD4D612, 0x03EB6F7D */
|
|
692
|
+
let pS2 = 2.01212532134862925881e-01W /* 0x3FC9C155, 0x0E884455 */
|
|
693
|
+
let pS3 = -4.00555345006794114027e-02W /* 0xBFA48228, 0xB5688F3B */
|
|
694
|
+
let pS4 = 7.91534994289814532176e-04W /* 0x3F49EFE0, 0x7501B288 */
|
|
695
|
+
let pS5 = 3.47933107596021167570e-05W /* 0x3F023DE1, 0x0DFDF709 */
|
|
696
|
+
let qS1 = -2.40339491173441421878e+00W /* 0xC0033A27, 0x1C8A2D4B */
|
|
697
|
+
let qS2 = 2.02094576023350569471e+00W /* 0x40002AE5, 0x9C598AC8 */
|
|
698
|
+
let qS3 = -6.88283971605453293030e-01W /* 0xBFE6066C, 0x1B8D0159 */
|
|
699
|
+
let qS4 = 7.70381505559019352791e-02W /* 0x3FB3B8C5, 0xB12E9282 */
|
|
700
|
+
// Calculations
|
|
701
|
+
let p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))))
|
|
702
|
+
let q = 1.0W + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)))
|
|
703
|
+
p / q
|
|
994
704
|
}
|
|
995
705
|
|
|
996
706
|
/**
|
|
997
|
-
* Computes the
|
|
707
|
+
* Computes the inverse sine of the given angle.
|
|
998
708
|
*
|
|
999
|
-
* @param
|
|
1000
|
-
* @returns The
|
|
709
|
+
* @param angle: A number between -1 and 1, representing the angle's sine value
|
|
710
|
+
* @returns The inverse sine (angle in radians between `-pi/2` and `pi/2`) of the given `angle` or `NaN` if the given `angle` is not between`-1` and `1`
|
|
1001
711
|
*
|
|
1002
|
-
* @
|
|
1003
|
-
* @
|
|
712
|
+
* @example Number.asin(0) == 0
|
|
713
|
+
* @example Number.asin(1) == 1.5707963267948966
|
|
714
|
+
*
|
|
715
|
+
* @since v0.6.0
|
|
1004
716
|
*/
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
717
|
+
@unsafe
|
|
718
|
+
provide let asin = angle => {
|
|
719
|
+
// see: musl/src/math/asin.c and SUN COPYRIGHT NOTICE at top of file
|
|
720
|
+
let origAngle = Numbers.coerceNumberToWasmF64(angle)
|
|
721
|
+
let mut x = origAngle
|
|
722
|
+
|
|
723
|
+
let pio2_hi = 1.57079632679489655800e+00W /* 0x3FF921FB, 0x54442D18 */
|
|
724
|
+
let pio2_lo = 6.12323399573676603587e-17W /* 0x3C91A626, 0x33145C07 */
|
|
725
|
+
|
|
726
|
+
use WasmI32.{ (&), (|), leU as (<), geU as (>=) }
|
|
727
|
+
use WasmI64.{ (>>>) }
|
|
728
|
+
use WasmF64.{ (+), (-), (*), (/) }
|
|
729
|
+
|
|
730
|
+
let hx = WasmI32.wrapI64(WasmI64.reinterpretF64(x) >>> 32N)
|
|
731
|
+
let ix = hx & 0x7fffffffn
|
|
732
|
+
/* |x| >= 1 or nan */
|
|
733
|
+
if (ix >= 0x3ff00000n) {
|
|
734
|
+
let lx = WasmI32.wrapI64(WasmI64.reinterpretF64(x))
|
|
735
|
+
use WasmI32.{ (-) }
|
|
736
|
+
/* asin(1) = +-pi/2 with inexact */
|
|
737
|
+
if (WasmI32.eqz(ix - 0x3ff00000n | lx))
|
|
738
|
+
return WasmI32.toGrain(newFloat64(x * pio2_hi + 0x1p-120W)): Number
|
|
739
|
+
return WasmI32.toGrain(newFloat64(NaNW)): Number
|
|
740
|
+
}
|
|
741
|
+
/* |x| < 0.5 */
|
|
742
|
+
if (ix < 0x3fe00000n) {
|
|
743
|
+
/* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
|
|
744
|
+
let output = if (ix < 0x3e500000n && ix >= 0x00100000n)
|
|
745
|
+
x
|
|
746
|
+
else
|
|
747
|
+
x + x * rf(x * x)
|
|
748
|
+
return WasmI32.toGrain(newFloat64(output)): Number
|
|
749
|
+
}
|
|
750
|
+
/* 1 > |x| >= 0.5 */
|
|
751
|
+
let z = (1.0W - WasmF64.abs(x)) * 0.5W
|
|
752
|
+
let s = WasmF64.sqrt(z)
|
|
753
|
+
let r = rf(z)
|
|
754
|
+
/* if |x| > 0.975 */
|
|
755
|
+
if (ix >= 0x3fef3333n) {
|
|
756
|
+
x = pio2_hi - (2.0W * (s + s * r) - pio2_lo)
|
|
1008
757
|
} else {
|
|
1009
|
-
|
|
758
|
+
use WasmI64.{ (&) }
|
|
759
|
+
/* f+c = sqrt(z) */
|
|
760
|
+
let f = WasmF64.reinterpretI64(
|
|
761
|
+
WasmI64.reinterpretF64(s) & 0xFFFFFFFF00000000N
|
|
762
|
+
)
|
|
763
|
+
let c = (z - f * f) / (s + f)
|
|
764
|
+
x = 0.5W * pio2_hi -
|
|
765
|
+
(2.0W * s * r - (pio2_lo - 2.0W * c) - (0.5W * pio2_hi - 2.0W * f))
|
|
1010
766
|
}
|
|
767
|
+
x = WasmF64.copySign(x, origAngle)
|
|
768
|
+
return WasmI32.toGrain(newFloat64(x)): Number
|
|
1011
769
|
}
|
|
1012
770
|
|
|
1013
771
|
/**
|
|
1014
|
-
* Computes the
|
|
772
|
+
* Computes the inverse cosine of the given angle.
|
|
1015
773
|
*
|
|
1016
|
-
* @param
|
|
1017
|
-
* @returns The
|
|
774
|
+
* @param angle: A number between -1 and 1, representing the angle's cosine value
|
|
775
|
+
* @returns The inverse cosine (angle in radians between `-pi/2` and `pi/2`) of the given `angle` or `NaN` if the given `angle` is not between`-1` and `1`
|
|
1018
776
|
*
|
|
1019
|
-
* @
|
|
777
|
+
* @example Number.acos(1) == 0
|
|
778
|
+
* @example Number.acos(0) == 1.5707963267948966
|
|
779
|
+
*
|
|
780
|
+
* @since v0.6.0
|
|
1020
781
|
*/
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
782
|
+
@unsafe
|
|
783
|
+
provide let acos = angle => {
|
|
784
|
+
// see: musl/src/math/acos.c and SUN COPYRIGHT NOTICE at top of file
|
|
785
|
+
let origAngle = Numbers.coerceNumberToWasmF64(angle)
|
|
786
|
+
let mut x = origAngle
|
|
787
|
+
|
|
788
|
+
let pio2_hi = 1.57079632679489655800e+00W /* 0x3FF921FB, 0x54442D18 */
|
|
789
|
+
let pio2_lo = 6.12323399573676603587e-17W /* 0x3C91A626, 0x33145C07 */
|
|
790
|
+
|
|
791
|
+
use WasmI32.{ (>>), (&), (|), (!=), leU as (<), geU as (>=), leU as (<=) }
|
|
792
|
+
use WasmI64.{ (>>>) }
|
|
793
|
+
use WasmF64.{ (+), (-), (*), (/) }
|
|
794
|
+
|
|
795
|
+
let hx = WasmI32.wrapI64(WasmI64.reinterpretF64(x) >>> 32N)
|
|
796
|
+
let ix = hx & 0x7fffffffn
|
|
797
|
+
|
|
798
|
+
/* |x| >= 1 or nan */
|
|
799
|
+
if (ix >= 0x3ff00000n) {
|
|
800
|
+
let lx = WasmI32.wrapI64(WasmI64.reinterpretF64(x))
|
|
801
|
+
use WasmI32.{ (-) }
|
|
802
|
+
if (WasmI32.eqz(ix - 0x3ff00000n | lx)) {
|
|
803
|
+
/* acos(1)=0, acos(-1)=pi */
|
|
804
|
+
if (hx >> 31n != 0n)
|
|
805
|
+
return WasmI32.toGrain(newFloat64(2.0W * pio2_hi + 0x1p-120W)): Number
|
|
806
|
+
else
|
|
807
|
+
return 0
|
|
808
|
+
}
|
|
809
|
+
return WasmI32.toGrain(newFloat64(NaNW)): Number
|
|
1026
810
|
}
|
|
811
|
+
/* |x| < 0.5 */
|
|
812
|
+
if (ix < 0x3fe00000n) {
|
|
813
|
+
/* |x| < 2**-57 */
|
|
814
|
+
let output = if (ix <= 0x3c600000n)
|
|
815
|
+
pio2_hi + 0x1p-120W
|
|
816
|
+
else
|
|
817
|
+
pio2_hi - (x - (pio2_lo - x * rf(x * x)))
|
|
818
|
+
return WasmI32.toGrain(newFloat64(output)): Number
|
|
819
|
+
}
|
|
820
|
+
/* x < -0.5 */
|
|
821
|
+
if (hx >> 31n != 0n) {
|
|
822
|
+
let z = (1.0W + x) * 0.5W
|
|
823
|
+
let s = WasmF64.sqrt(z)
|
|
824
|
+
let w = rf(z) * s - pio2_lo
|
|
825
|
+
return WasmI32.toGrain(newFloat64(2.0W * (pio2_hi - (s + w)))): Number
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/* x > 0.5 */
|
|
829
|
+
use WasmI64.{ (&) }
|
|
830
|
+
let z = (1.0W - x) * 0.5W
|
|
831
|
+
let s = WasmF64.sqrt(z)
|
|
832
|
+
let df = WasmF64.reinterpretI64(
|
|
833
|
+
WasmI64.reinterpretF64(s) & 0xFFFFFFFF00000000N
|
|
834
|
+
)
|
|
835
|
+
let c = (z - df * df) / (s + df)
|
|
836
|
+
let w = rf(z) * s + c
|
|
837
|
+
return WasmI32.toGrain(newFloat64(2.0W * (df + w))): Number
|
|
1027
838
|
}
|
|
1028
839
|
|
|
1029
|
-
// Math.gamma implemented using the Lanczos approximation
|
|
1030
|
-
// https://en.wikipedia.org/wiki/Lanczos_approximation
|
|
1031
840
|
/**
|
|
1032
|
-
* Computes the
|
|
841
|
+
* Computes the inverse tangent of the given angle.
|
|
1033
842
|
*
|
|
1034
|
-
* @param
|
|
1035
|
-
* @returns The
|
|
843
|
+
* @param angle: A number between -1 and 1, representing the angle's tangent value
|
|
844
|
+
* @returns The inverse tangent (angle in radians between `-pi/2` and `pi/2`) of the given `angle` or `NaN` if the given `angle` is not between`-1` and `1`
|
|
1036
845
|
*
|
|
1037
|
-
* @
|
|
846
|
+
* @example Number.atan(0) == 0
|
|
847
|
+
* @example Number.atan(1) == 0.7853981633974483
|
|
1038
848
|
*
|
|
1039
|
-
* @since v0.
|
|
849
|
+
* @since v0.6.0
|
|
1040
850
|
*/
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
851
|
+
@unsafe
|
|
852
|
+
provide let atan = angle => {
|
|
853
|
+
// see: musl/src/math/asin.c and SUN COPYRIGHT NOTICE at top of file
|
|
854
|
+
let origAngle = Numbers.coerceNumberToWasmF64(angle)
|
|
855
|
+
let mut x = origAngle
|
|
856
|
+
// Constants
|
|
857
|
+
let atanhi0 = 4.63647609000806093515e-01W // atan(0.5)hi 0x3FDDAC67, 0x0561BB4F
|
|
858
|
+
let atanhi1 = 7.85398163397448278999e-01W // atan(1.0)hi 0x3FE921FB, 0x54442D18
|
|
859
|
+
let atanhi2 = 9.82793723247329054082e-01W // atan(1.5)hi 0x3FEF730B, 0xD281F69B
|
|
860
|
+
let atanhi3 = 1.57079632679489655800e+00W // atan(inf)hi 0x3FF921FB, 0x54442D18
|
|
861
|
+
let atanlo0 = 2.26987774529616870924e-17W // atan(0.5)lo 0x3C7A2B7F, 0x222F65E2
|
|
862
|
+
let atanlo1 = 3.06161699786838301793e-17W // atan(1.0)lo 0x3C81A626, 0x33145C07
|
|
863
|
+
let atanlo2 = 1.39033110312309984516e-17W // atan(1.5)lo 0x3C700788, 0x7AF0CBBD
|
|
864
|
+
let atanlo3 = 6.12323399573676603587e-17W // atan(inf)lo 0x3C91A626, 0x33145C07
|
|
865
|
+
let aT0 = 3.33333333333329318027e-01W // 0x3FD55555, 0x5555550D
|
|
866
|
+
let aT1 = -1.99999999998764832476e-01W // 0xBFC99999, 0x9998EBC4
|
|
867
|
+
let aT2 = 1.42857142725034663711e-01W // 0x3FC24924, 0x920083FF
|
|
868
|
+
let aT3 = -1.11111104054623557880e-01W // 0xBFBC71C6, 0xFE231671
|
|
869
|
+
let aT4 = 9.09088713343650656196e-02W // 0x3FB745CD, 0xC54C206E
|
|
870
|
+
let aT5 = -7.69187620504482999495e-02W // 0xBFB3B0F2, 0xAF749A6D
|
|
871
|
+
let aT6 = 6.66107313738753120669e-02W // 0x3FB10D66, 0xA0D03D51
|
|
872
|
+
let aT7 = -5.83357013379057348645e-02W // 0xBFADDE2D, 0x52DEFD9A
|
|
873
|
+
let aT8 = 4.97687799461593236017e-02W // 0x3FA97B4B, 0x24760DEB
|
|
874
|
+
let aT9 = -3.65315727442169155270e-02W // 0xBFA2B444, 0x2C6A6C2F
|
|
875
|
+
let aT10 = 1.62858201153657823623e-02W // 0x3F90AD3A, 0xE322DA11
|
|
876
|
+
// Operators
|
|
877
|
+
use WasmI32.{ (&), (<), (>=), (==) }
|
|
878
|
+
use WasmI64.{ (>>>) }
|
|
879
|
+
use WasmF64.{ (+), (-), (*), (/) }
|
|
880
|
+
// Calculations
|
|
881
|
+
let ix = WasmI32.wrapI64(WasmI64.reinterpretF64(x) >>> 32N)
|
|
882
|
+
let sx = x
|
|
883
|
+
let ix = ix & 0x7FFFFFFFn
|
|
884
|
+
/* if |x| >= 2^66 */
|
|
885
|
+
if (ix >= 0x44100000n) {
|
|
886
|
+
if (isNaN(angle)) return NaN
|
|
887
|
+
let z = atanhi3 + 0x1p-120W
|
|
888
|
+
return WasmI32.toGrain(newFloat64(WasmF64.copySign(z, sx))): Number
|
|
889
|
+
}
|
|
890
|
+
let mut id = 3n
|
|
891
|
+
/* |x| < 0.4375 */
|
|
892
|
+
if (ix < 0x3FDC0000n) {
|
|
893
|
+
/* |x| < 2^-27 */
|
|
894
|
+
if (ix < 0x3E400000n) return angle
|
|
895
|
+
id = -1n
|
|
1050
896
|
} else {
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
1.5056327351493116e-7,
|
|
1063
|
-
]
|
|
1064
|
-
let mut output = 0
|
|
1065
|
-
if (z < 0.5) {
|
|
1066
|
-
output = pi / (sin(pi * z) * gamma(1 - z))
|
|
1067
|
-
} else if (z == 0.5) {
|
|
1068
|
-
// Handle this case separately because it is out of the domain of Number.pow when calculating
|
|
1069
|
-
output = 1.7724538509055159
|
|
897
|
+
x = WasmF64.abs(x)
|
|
898
|
+
/* |x| < 1.1875 */
|
|
899
|
+
if (ix < 0x3FF30000n) {
|
|
900
|
+
/* 7/16 <= |x| < 11/16 */
|
|
901
|
+
if (ix < 0x3FE60000n) {
|
|
902
|
+
id = 0n
|
|
903
|
+
x = (2.0W * x - 1.0W) / (2.0W + x)
|
|
904
|
+
} else { /* 11/16 <= |x| < 19/16 */
|
|
905
|
+
id = 1n
|
|
906
|
+
x = (x - 1.0W) / (x + 1.0W)
|
|
907
|
+
}
|
|
1070
908
|
} else {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
x
|
|
909
|
+
/* |x| < 2.4375 */
|
|
910
|
+
if (ix < 0x40038000n) {
|
|
911
|
+
id = 2n
|
|
912
|
+
x = (x - 1.5W) / (1.0W + 1.5W * x)
|
|
913
|
+
} else { /* 2.4375 <= |x| < 2^66 */
|
|
914
|
+
x = -1.0W / x
|
|
1075
915
|
}
|
|
1076
|
-
|
|
1077
|
-
let t = z + g + 0.5
|
|
1078
|
-
output = sqrt(2 * pi) * pow(t, z + 0.5) * exp(t * -1) * x
|
|
1079
916
|
}
|
|
1080
|
-
if (abs(output) == infinity) infinity else output
|
|
1081
917
|
}
|
|
918
|
+
let z = x * x
|
|
919
|
+
let w = z * z
|
|
920
|
+
let s1 = z * (aT0 + w * (aT2 + w * (aT4 + w * (aT6 + w * (aT8 + w * aT10)))))
|
|
921
|
+
let s2 = w * (aT1 + w * (aT3 + w * (aT5 + w * (aT7 + w * aT9))))
|
|
922
|
+
let s3 = x * (s1 + s2)
|
|
923
|
+
use WasmI32.{ (<) }
|
|
924
|
+
if (id < 0n)
|
|
925
|
+
return WasmI32.toGrain(newFloat64(WasmF64.copySign(x - s3, sx))): Number
|
|
926
|
+
let mut z = 0.0W
|
|
927
|
+
match (id) {
|
|
928
|
+
0n => z = atanhi0 - (s3 - atanlo0 - x),
|
|
929
|
+
1n => z = atanhi1 - (s3 - atanlo1 - x),
|
|
930
|
+
2n => z = atanhi2 - (s3 - atanlo2 - x),
|
|
931
|
+
3n => z = atanhi3 - (s3 + atanlo3 - x),
|
|
932
|
+
_ => fail "Unreachable",
|
|
933
|
+
}
|
|
934
|
+
return WasmI32.toGrain(newFloat64(WasmF64.copySign(z, sx))): Number
|
|
1082
935
|
}
|
|
1083
936
|
|
|
1084
937
|
/**
|
|
1085
|
-
* Computes the
|
|
938
|
+
* Computes the angle between the positive x-axis and the ray from the origin to the point (x, y).
|
|
1086
939
|
*
|
|
1087
|
-
* @param
|
|
1088
|
-
* @
|
|
940
|
+
* @param y: The given y coordinate
|
|
941
|
+
* @param x: The given x coordinate
|
|
942
|
+
* @returns The angle in radians between the positive x-axis and the point (x, y)
|
|
1089
943
|
*
|
|
1090
|
-
* @
|
|
944
|
+
* @example Number.atan2(0, 1) == Number.pi
|
|
1091
945
|
*
|
|
1092
|
-
* @since v0.
|
|
946
|
+
* @since v0.6.0
|
|
1093
947
|
*/
|
|
1094
|
-
|
|
1095
|
-
if (
|
|
1096
|
-
|
|
1097
|
-
) {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
)
|
|
1101
|
-
} else {
|
|
1102
|
-
|
|
948
|
+
provide let atan2 = (y, x) => {
|
|
949
|
+
if (x > 0) {
|
|
950
|
+
atan(y / x)
|
|
951
|
+
} else if (x < 0 && y >= 0) {
|
|
952
|
+
atan(y / x) + pi
|
|
953
|
+
} else if (x < 0 && y < 0) {
|
|
954
|
+
atan(y / x) - pi
|
|
955
|
+
} else if (x == 0 && y > 0) {
|
|
956
|
+
pi / 2
|
|
957
|
+
} else if (x == 0 && y < 0) {
|
|
958
|
+
pi / -2
|
|
959
|
+
} else { // x == 0 && y == 0
|
|
960
|
+
0
|
|
1103
961
|
}
|
|
1104
962
|
}
|
|
1105
963
|
|
|
@@ -1109,9 +967,11 @@ export let rec factorial = n => {
|
|
|
1109
967
|
* @param degrees: The value to convert
|
|
1110
968
|
* @returns The value in radians
|
|
1111
969
|
*
|
|
970
|
+
* @example Number.toRadians(180) == Number.pi
|
|
971
|
+
*
|
|
1112
972
|
* @since v0.5.4
|
|
1113
973
|
*/
|
|
1114
|
-
|
|
974
|
+
provide let toRadians = degrees => degrees * (pi / 180)
|
|
1115
975
|
|
|
1116
976
|
/**
|
|
1117
977
|
* Converts radians to degrees.
|
|
@@ -1119,6 +979,96 @@ export let toRadians = degrees => degrees * (pi / 180)
|
|
|
1119
979
|
* @param radians: The value to convert
|
|
1120
980
|
* @returns The value in degrees
|
|
1121
981
|
*
|
|
982
|
+
* @example Number.toRadians(Number.pi) == 180
|
|
983
|
+
*
|
|
1122
984
|
* @since v0.5.4
|
|
1123
985
|
*/
|
|
1124
|
-
|
|
986
|
+
provide let toDegrees = radians => radians * (180 / pi)
|
|
987
|
+
|
|
988
|
+
// TODO(#471): Add examples for clamp
|
|
989
|
+
/**
|
|
990
|
+
* Constrains a number within the given inclusive range.
|
|
991
|
+
*
|
|
992
|
+
* @param range: The inclusive range to clamp within
|
|
993
|
+
* @param input: The number to clamp
|
|
994
|
+
* @returns The constrained number
|
|
995
|
+
*
|
|
996
|
+
* @since v0.6.0
|
|
997
|
+
*/
|
|
998
|
+
provide let clamp = (range, input) => {
|
|
999
|
+
if (isNaN(input)) {
|
|
1000
|
+
input
|
|
1001
|
+
} else {
|
|
1002
|
+
let rangeEnd = max(range.rangeStart, range.rangeEnd)
|
|
1003
|
+
let rangeStart = min(range.rangeStart, range.rangeEnd)
|
|
1004
|
+
|
|
1005
|
+
if (input > rangeEnd) {
|
|
1006
|
+
rangeEnd
|
|
1007
|
+
} else if (input < rangeStart) {
|
|
1008
|
+
rangeStart
|
|
1009
|
+
} else {
|
|
1010
|
+
input
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// TODO(#471): Add examples for linearInterpolate
|
|
1016
|
+
/**
|
|
1017
|
+
* Maps a weight between 0 and 1 within the given inclusive range.
|
|
1018
|
+
*
|
|
1019
|
+
* @param range: The inclusive range to interpolate within
|
|
1020
|
+
* @param weight: The weight to interpolate
|
|
1021
|
+
* @returns The blended value
|
|
1022
|
+
*
|
|
1023
|
+
* @throws InvalidArgument(String): When `weight` is not between 0 and 1
|
|
1024
|
+
* @throws InvalidArgument(String): When `range` is not finite
|
|
1025
|
+
* @throws InvalidArgument(String): When `range` includes NaN
|
|
1026
|
+
*
|
|
1027
|
+
* @since v0.6.0
|
|
1028
|
+
*/
|
|
1029
|
+
provide let linearInterpolate = (range, weight) => {
|
|
1030
|
+
if (weight < 0 || weight > 1 || isNaN(weight))
|
|
1031
|
+
throw Exception.InvalidArgument("Weight must be between 0 and 1")
|
|
1032
|
+
if (isInfinite(range.rangeStart) || isInfinite(range.rangeEnd))
|
|
1033
|
+
throw Exception.InvalidArgument("The range must be finite")
|
|
1034
|
+
if (isNaN(range.rangeStart) || isNaN(range.rangeEnd))
|
|
1035
|
+
throw Exception.InvalidArgument("The range must not include NaN")
|
|
1036
|
+
(range.rangeEnd - range.rangeStart) * weight + range.rangeStart
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// TODO(#471): Add examples for linearMap
|
|
1040
|
+
/**
|
|
1041
|
+
* Scales a number from one inclusive range to another inclusive range.
|
|
1042
|
+
* If the number is outside the input range, it will be clamped.
|
|
1043
|
+
*
|
|
1044
|
+
* @param inputRange: The inclusive range you are mapping from
|
|
1045
|
+
* @param outputRange: The inclusive range you are mapping to
|
|
1046
|
+
* @param current: The number to map
|
|
1047
|
+
* @returns The mapped number
|
|
1048
|
+
*
|
|
1049
|
+
* @throws InvalidArgument(String): When `inputRange` is not finite
|
|
1050
|
+
* @throws InvalidArgument(String): When `inputRange` includes NaN
|
|
1051
|
+
* @throws InvalidArgument(String): When `outputRange` is not finite
|
|
1052
|
+
* @throws InvalidArgument(String): When `outputRange` includes NaN
|
|
1053
|
+
*
|
|
1054
|
+
* @since v0.6.0
|
|
1055
|
+
*/
|
|
1056
|
+
provide let linearMap = (inputRange, outputRange, current) => {
|
|
1057
|
+
if (isNaN(current)) {
|
|
1058
|
+
current
|
|
1059
|
+
} else {
|
|
1060
|
+
if (isInfinite(inputRange.rangeStart) || isInfinite(inputRange.rangeEnd))
|
|
1061
|
+
throw Exception.InvalidArgument("The inputRange must be finite")
|
|
1062
|
+
if (isNaN(inputRange.rangeStart) || isNaN(inputRange.rangeEnd))
|
|
1063
|
+
throw Exception.InvalidArgument("The inputRange must not include NaN")
|
|
1064
|
+
if (isInfinite(outputRange.rangeStart) || isInfinite(outputRange.rangeEnd))
|
|
1065
|
+
throw Exception.InvalidArgument("The outputRange must be finite")
|
|
1066
|
+
if (isNaN(outputRange.rangeStart) || isNaN(outputRange.rangeEnd))
|
|
1067
|
+
throw Exception.InvalidArgument("The outputRange must not include NaN")
|
|
1068
|
+
let mapped = (current - inputRange.rangeStart) *
|
|
1069
|
+
(outputRange.rangeEnd - outputRange.rangeStart) /
|
|
1070
|
+
(inputRange.rangeEnd - inputRange.rangeStart) +
|
|
1071
|
+
outputRange.rangeStart
|
|
1072
|
+
clamp(outputRange, mapped)
|
|
1073
|
+
}
|
|
1074
|
+
}
|