@grain/stdlib 0.5.13 → 0.6.1
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 +201 -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 +62 -40
- package/hash.md +27 -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 +2071 -0
- package/json.md +646 -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 +193 -174
- package/runtime/numberUtils.md +29 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +543 -245
- 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/runtime/atof/lemire.gr
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* grainc-flags --no-pervasives */
|
|
2
|
-
|
|
3
1
|
// This module was based on Rust's dec2flt
|
|
4
2
|
// https://github.com/rust-lang/rust/blob/1cbc45942d5c0f6eb5d94e3b10762ba541958035/library/core/src/num/dec2flt/lemire.rs
|
|
5
3
|
// Rust's MIT license is provided below:
|
|
@@ -13,11 +11,11 @@
|
|
|
13
11
|
* the Software, and to permit persons to whom the Software
|
|
14
12
|
* is furnished to do so, subject to the following
|
|
15
13
|
* conditions:
|
|
16
|
-
*
|
|
14
|
+
*
|
|
17
15
|
* The above copyright notice and this permission notice
|
|
18
16
|
* shall be included in all copies or substantial portions
|
|
19
17
|
* of the Software.
|
|
20
|
-
*
|
|
18
|
+
*
|
|
21
19
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
22
20
|
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
23
21
|
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
@@ -28,14 +26,19 @@
|
|
|
28
26
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
29
27
|
* DEALINGS IN THE SOFTWARE.
|
|
30
28
|
*/
|
|
29
|
+
@noPervasives
|
|
30
|
+
module Lemire
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
33
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
from "runtime/dataStructures" include DataStructures
|
|
36
|
+
use DataStructures.{ newInt32, newInt64, newFloat64 }
|
|
37
|
+
from "runtime/atof/table" include Table
|
|
38
|
+
use Table.{ get_POWERS5 }
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
from "runtime/atof/common" include Common
|
|
41
|
+
use Common.{
|
|
39
42
|
_SMALLEST_POWER_OF_FIVE,
|
|
40
43
|
_LARGEST_POWER_OF_FIVE,
|
|
41
44
|
_INFINITE_POWER,
|
|
@@ -48,15 +51,15 @@ import {
|
|
|
48
51
|
_MAX_EXPONENT_ROUND_TO_EVEN,
|
|
49
52
|
fullMultiplication,
|
|
50
53
|
power,
|
|
51
|
-
BiasedFp,
|
|
54
|
+
type BiasedFp,
|
|
52
55
|
fpZero,
|
|
53
56
|
fpInf,
|
|
54
57
|
fpErr,
|
|
55
|
-
}
|
|
58
|
+
}
|
|
56
59
|
|
|
57
|
-
primitive (&&)
|
|
58
|
-
primitive (||)
|
|
59
|
-
primitive (!)
|
|
60
|
+
primitive (&&) = "@and"
|
|
61
|
+
primitive (||) = "@or"
|
|
62
|
+
primitive (!) = "@not"
|
|
60
63
|
|
|
61
64
|
// From Rust:
|
|
62
65
|
// This will compute or rather approximate w * 5**q and return a pair of 64-bit words
|
|
@@ -64,18 +67,11 @@ primitive (!): Bool -> Bool = "@not"
|
|
|
64
67
|
// bits and the low part corresponding to the least significant bits.
|
|
65
68
|
@unsafe
|
|
66
69
|
let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
let (>) = WasmI64.gtU
|
|
70
|
-
let (<) = WasmI64.ltU
|
|
71
|
-
let (>=) = WasmI64.geS
|
|
72
|
-
let (<=) = WasmI64.leS
|
|
73
|
-
let (>>) = WasmI64.shrU
|
|
74
|
-
let (-) = WasmI64.sub
|
|
75
|
-
let (+) = WasmI64.add
|
|
70
|
+
use WasmI64.{ (==), (&), gtU as (>), ltU as (<), (>=), (<=), (>>>), (-), (+) }
|
|
71
|
+
use WasmI32.{ (*) }
|
|
76
72
|
|
|
77
73
|
let mask = if (precision < 64N) {
|
|
78
|
-
0xFFFF_FFFF_FFFF_FFFFN
|
|
74
|
+
0xFFFF_FFFF_FFFF_FFFFN >>> precision
|
|
79
75
|
} else {
|
|
80
76
|
0xFFFF_FFFF_FFFF_FFFFN
|
|
81
77
|
}
|
|
@@ -85,10 +81,11 @@ let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
|
|
|
85
81
|
// That means whenever we need to round ties to even, we always have
|
|
86
82
|
// an exact value.
|
|
87
83
|
let index = q - _SMALLEST_POWER_OF_FIVE
|
|
88
|
-
let n =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
let n = 16n * WasmI32.wrapI64(index)
|
|
85
|
+
use WasmI32.{ (+) }
|
|
86
|
+
let lo5 = WasmI64.load(get_POWERS5(), n)
|
|
87
|
+
and hi5 = WasmI64.load(get_POWERS5(), n + 8n)
|
|
88
|
+
use WasmI64.{ (+) }
|
|
92
89
|
// From Rust:
|
|
93
90
|
// Only need one multiplication as long as there is 1 zero but
|
|
94
91
|
// in the explicit mantissa bits, +1 for the hidden bit, +1 to
|
|
@@ -120,16 +117,8 @@ let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
|
|
|
120
117
|
// Returns the significant bits and a biased binary exponent that can be directly shifted into exponent bits:
|
|
121
118
|
// (u64, i32)
|
|
122
119
|
@unsafe
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
let (<) = WasmI64.ltS
|
|
126
|
-
let (<=) = WasmI64.leS
|
|
127
|
-
let (>) = WasmI64.gtS
|
|
128
|
-
let (>=) = WasmI64.geS
|
|
129
|
-
let (<<) = WasmI64.shl
|
|
130
|
-
let (>>) = WasmI64.shrS
|
|
131
|
-
let (&) = WasmI64.and
|
|
132
|
-
let (+) = WasmI64.add
|
|
120
|
+
provide let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
|
|
121
|
+
use WasmI64.{ (==), (<), (<=), (>), (>=), (<<), (>>), (&), (+), (>>>) }
|
|
133
122
|
|
|
134
123
|
let w = mantissa
|
|
135
124
|
let q = exponent
|
|
@@ -163,33 +152,30 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
|
|
|
163
152
|
match (lo == 0xFFFF_FFFF_FFFF_FFFFN && !(q >= -27N && q <= 55N)) {
|
|
164
153
|
true => fpErr(),
|
|
165
154
|
false => {
|
|
166
|
-
let upperbit = WasmI32.wrapI64(
|
|
167
|
-
let mut mantissa = WasmI64.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let (+) = WasmI32.add
|
|
172
|
-
let (-) = WasmI32.sub
|
|
173
|
-
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
174
|
-
}
|
|
175
|
-
)
|
|
176
|
-
)
|
|
155
|
+
let upperbit = WasmI32.wrapI64(hi >>> 63N)
|
|
156
|
+
let mut mantissa = hi >>> WasmI64.extendI32S({
|
|
157
|
+
use WasmI32.{ (+), (-) }
|
|
158
|
+
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
159
|
+
})
|
|
177
160
|
let mut power2 = {
|
|
178
|
-
|
|
179
|
-
let (-) = WasmI32.sub
|
|
161
|
+
use WasmI32.{ (+), (-) }
|
|
180
162
|
let q = WasmI32.wrapI64(q)
|
|
181
163
|
let lz = WasmI32.wrapI64(lz)
|
|
182
164
|
power(q) + upperbit - lz - _MINIMUM_EXPONENT
|
|
183
165
|
}
|
|
184
|
-
|
|
166
|
+
|
|
167
|
+
use WasmI32.{ (<=) }
|
|
168
|
+
if (power2 <= 0n) {
|
|
169
|
+
use WasmI32.{ (+), (*), (>=) }
|
|
185
170
|
// -power2 + 1 >= 64
|
|
186
|
-
if (
|
|
171
|
+
if (-1n * power2 + 1n >= 64n) {
|
|
187
172
|
// Have more than 64 bits below the minimum exponent, must be 0.
|
|
188
173
|
fpZero()
|
|
189
174
|
} else {
|
|
175
|
+
use WasmI64.{ (>=) }
|
|
190
176
|
// Have a subnormal value.
|
|
191
|
-
mantissa = mantissa >>
|
|
192
|
-
|
|
177
|
+
mantissa = mantissa >> WasmI64.extendI32S(-1n * power2 + 1n)
|
|
178
|
+
use WasmI64.{ (+) }
|
|
193
179
|
mantissa += mantissa & 1N
|
|
194
180
|
mantissa = mantissa >> 1N
|
|
195
181
|
power2 = if (mantissa >= 1N << _MANTISSA_EXPLICIT_BITS_64) {
|
|
@@ -204,6 +190,7 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
|
|
|
204
190
|
}
|
|
205
191
|
}
|
|
206
192
|
} else {
|
|
193
|
+
use WasmI64.{ (<=) }
|
|
207
194
|
// Need to handle rounding ties. Normally, we need to round up,
|
|
208
195
|
// but if we fall right in between and and we have an even basis, we
|
|
209
196
|
// need to round down.
|
|
@@ -220,38 +207,36 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
|
|
|
220
207
|
q >= _MIN_EXPONENT_ROUND_TO_EVEN &&
|
|
221
208
|
q <= _MAX_EXPONENT_ROUND_TO_EVEN &&
|
|
222
209
|
(mantissa & 3N) == 1N &&
|
|
223
|
-
mantissa <<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
let (-) = WasmI32.sub
|
|
228
|
-
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
229
|
-
}
|
|
230
|
-
) ==
|
|
231
|
-
hi
|
|
210
|
+
mantissa << WasmI64.extendI32S({
|
|
211
|
+
use WasmI32.{ (+), (-) }
|
|
212
|
+
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
213
|
+
}) == hi
|
|
232
214
|
) {
|
|
215
|
+
use WasmI64.{ (^) }
|
|
233
216
|
// Zero the lowest bit, so we don't round up.
|
|
234
217
|
// mantissa &= !1N;
|
|
235
|
-
mantissa = mantissa &
|
|
218
|
+
mantissa = mantissa & (1N ^ -1N)
|
|
236
219
|
}
|
|
237
220
|
// Round-to-even, then shift the significant digits into place.
|
|
238
221
|
mantissa += mantissa & 1N
|
|
239
|
-
|
|
222
|
+
use WasmI64.{ (>>>) }
|
|
223
|
+
mantissa = mantissa >>> 1N
|
|
240
224
|
if (WasmI64.geU(mantissa, 2N << _MANTISSA_EXPLICIT_BITS_64)) {
|
|
225
|
+
use WasmI32.{ (+) }
|
|
241
226
|
// Rounding up overflowed, so the carry bit is set. Set the
|
|
242
227
|
// mantissa to 1 (only the implicit, hidden bit is set) and
|
|
243
228
|
// increase the exponent.
|
|
244
229
|
mantissa = 1N << _MANTISSA_EXPLICIT_BITS_64
|
|
245
|
-
power2
|
|
230
|
+
power2 += 1n
|
|
246
231
|
}
|
|
232
|
+
use WasmI32.{ (>=) }
|
|
233
|
+
use WasmI64.{ (^) }
|
|
247
234
|
// Zero out the hidden bit.
|
|
248
|
-
mantissa = mantissa &
|
|
249
|
-
|
|
250
|
-
if (WasmI32.geS(power2, _INFINITE_POWER)) {
|
|
235
|
+
mantissa = mantissa & (1N << _MANTISSA_EXPLICIT_BITS_64 ^ -1N)
|
|
236
|
+
if (power2 >= _INFINITE_POWER) {
|
|
251
237
|
// Exponent is above largest normal value, must be infinite.
|
|
252
238
|
fpInf()
|
|
253
239
|
} else {
|
|
254
|
-
|
|
255
240
|
{
|
|
256
241
|
f: WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
257
242
|
e: WasmI32.toGrain(newInt32(power2)): Int32,
|
package/runtime/atof/lemire.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Lemire
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Values
|
|
6
|
+
|
|
7
|
+
Functions and constants included in the Lemire module.
|
|
8
|
+
|
|
1
9
|
### Lemire.**computeFloat**
|
|
2
10
|
|
|
3
11
|
```grain
|
|
4
|
-
computeFloat : (WasmI64, WasmI64)
|
|
12
|
+
computeFloat : (exponent: WasmI64, mantissa: WasmI64) => Common.BiasedFp
|
|
5
13
|
```
|
|
6
14
|
|
package/runtime/atof/parse.gr
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* the Software, and to permit persons to whom the Software
|
|
12
12
|
* is furnished to do so, subject to the following
|
|
13
13
|
* conditions:
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* The above copyright notice and this permission notice
|
|
16
16
|
* shall be included in all copies or substantial portions
|
|
17
17
|
* of the Software.
|
|
18
|
-
*
|
|
18
|
+
*
|
|
19
19
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
20
20
|
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
21
21
|
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
@@ -26,13 +26,16 @@
|
|
|
26
26
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
27
27
|
* DEALINGS IN THE SOFTWARE.
|
|
28
28
|
*/
|
|
29
|
+
module Parse
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
32
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
33
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
34
|
+
from "runtime/dataStructures" include DataStructures
|
|
35
|
+
use DataStructures.{ newInt32, newInt64, newFloat64 }
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
from "runtime/atof/common" include Common
|
|
38
|
+
use Common.{
|
|
36
39
|
_CHAR_CODE_UNDERSCORE,
|
|
37
40
|
_CHAR_CODE_PLUS,
|
|
38
41
|
_CHAR_CODE_MINUS,
|
|
@@ -58,41 +61,32 @@ import {
|
|
|
58
61
|
biasedFpToNumber,
|
|
59
62
|
fpNan,
|
|
60
63
|
fpInf,
|
|
61
|
-
}
|
|
64
|
+
}
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
from "runtime/atof/lemire" include Lemire
|
|
67
|
+
use Lemire.{ computeFloat }
|
|
68
|
+
from "runtime/atof/slow" include Slow
|
|
69
|
+
use Slow.{ parseLongMantissa }
|
|
65
70
|
|
|
66
71
|
// Try to parse 8 digits at a time:
|
|
67
72
|
// https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
|
68
73
|
@unsafe
|
|
69
74
|
let parse8Digits = (digits: WasmI64) => {
|
|
70
|
-
|
|
71
|
-
let (-) = WasmI64.sub
|
|
72
|
-
let (*) = WasmI64.mul
|
|
73
|
-
let (>>) = WasmI64.shrU
|
|
74
|
-
let (&) = WasmI64.and
|
|
75
|
-
let (|) = WasmI64.or
|
|
76
|
-
let (==) = WasmI64.eq
|
|
75
|
+
use WasmI64.{ (+), (-), (*), (>>>), (&), (|), (==) }
|
|
77
76
|
|
|
78
77
|
let _MASK = 0x0000_00FF_0000_00FFN
|
|
79
78
|
|
|
80
79
|
let a = digits - 0x3030_3030_3030_3030N
|
|
81
|
-
let b = a * 10N + (a
|
|
80
|
+
let b = a * 10N + (a >>> 8N)
|
|
82
81
|
let c = (b & _MASK) * 0x000F_4240_0000_0064N
|
|
83
|
-
let d = (b
|
|
82
|
+
let d = (b >>> 16N & _MASK) * 0x0000_2710_0000_0001N
|
|
84
83
|
|
|
85
|
-
(c + d)
|
|
84
|
+
(c + d) >>> 32N
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
@unsafe
|
|
89
88
|
let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
|
|
90
|
-
|
|
91
|
-
let (-) = WasmI32.sub
|
|
92
|
-
let (>=) = WasmI32.geU
|
|
93
|
-
let (<) = WasmI32.ltU
|
|
94
|
-
let (==) = WasmI32.eq
|
|
95
|
-
let (!=) = WasmI32.ne
|
|
89
|
+
use WasmI32.{ (+), (-), (*), geU as (>=), ltU as (<), (==), (!=) }
|
|
96
90
|
|
|
97
91
|
let mut offset = offset
|
|
98
92
|
let mut exponent = 0n
|
|
@@ -119,8 +113,9 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
|
|
|
119
113
|
let char = WasmI32.load8U(ptr, offset)
|
|
120
114
|
let digit = char - 0x30n
|
|
121
115
|
if (digit >= 0n && digit < 10n) {
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
use WasmI32.{ (<) }
|
|
117
|
+
if (exponent < 0x10000n) {
|
|
118
|
+
exponent = digit + 10n * exponent
|
|
124
119
|
}
|
|
125
120
|
offset += 1n
|
|
126
121
|
} else if (char == _CHAR_CODE_UNDERSCORE) {
|
|
@@ -132,7 +127,7 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
|
|
|
132
127
|
if (offset != len) {
|
|
133
128
|
Err("Invalid exponent")
|
|
134
129
|
} else if (negative) {
|
|
135
|
-
Ok(WasmI32.toGrain(newInt32(
|
|
130
|
+
Ok(WasmI32.toGrain(newInt32(0n - exponent)): Int32)
|
|
136
131
|
} else {
|
|
137
132
|
Ok(WasmI32.toGrain(newInt32(exponent)): Int32)
|
|
138
133
|
}
|
|
@@ -141,13 +136,8 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
|
|
|
141
136
|
|
|
142
137
|
@unsafe
|
|
143
138
|
let parseFloatToParts = (string: String) => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let (>) = WasmI32.gtU
|
|
147
|
-
let (>=) = WasmI32.geU
|
|
148
|
-
let (<) = WasmI32.ltU
|
|
149
|
-
let (==) = WasmI32.eq
|
|
150
|
-
let (!=) = WasmI32.ne
|
|
139
|
+
use WasmI32.{ (+), (-), gtU as (>), geU as (>=), ltU as (<), (==), (!=) }
|
|
140
|
+
use WasmI64.{ (+) as addWasmI64, (*) }
|
|
151
141
|
|
|
152
142
|
let ptr = WasmI32.fromGrain(string)
|
|
153
143
|
match (WasmI32.load(ptr, 4n)) {
|
|
@@ -183,10 +173,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
183
173
|
let char = WasmI32.load8U(ptr, i)
|
|
184
174
|
let digit = char - _CHAR_CODE_0
|
|
185
175
|
if (digit >= 0n && digit < 10n) {
|
|
186
|
-
mantissa = WasmI64.
|
|
187
|
-
WasmI64.mul(mantissa, 10N),
|
|
188
|
-
WasmI64.extendI32U(digit)
|
|
189
|
-
)
|
|
176
|
+
mantissa = addWasmI64(mantissa * 10N, WasmI64.extendI32U(digit))
|
|
190
177
|
numDigits += 1n
|
|
191
178
|
i += 1n
|
|
192
179
|
} else if (char == _CHAR_CODE_UNDERSCORE) {
|
|
@@ -207,10 +194,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
207
194
|
while (WasmI32.leU(i + 8n, len)) {
|
|
208
195
|
let digits = WasmI64.load(ptr, i)
|
|
209
196
|
if (is8Digits(digits)) {
|
|
210
|
-
mantissa =
|
|
211
|
-
parse8Digits(digits),
|
|
212
|
-
WasmI64.mul(mantissa, 100000000N)
|
|
213
|
-
)
|
|
197
|
+
mantissa = addWasmI64(parse8Digits(digits), mantissa * 100000000N)
|
|
214
198
|
i += 8n
|
|
215
199
|
numDigitsAfterDot += 8n
|
|
216
200
|
} else {
|
|
@@ -222,10 +206,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
222
206
|
let char = WasmI32.load8U(ptr, i)
|
|
223
207
|
let digit = char - _CHAR_CODE_0
|
|
224
208
|
if (digit >= 0n && digit < 10n) {
|
|
225
|
-
mantissa = WasmI64.
|
|
226
|
-
WasmI64.extendI32U(digit),
|
|
227
|
-
WasmI64.mul(mantissa, 10N)
|
|
228
|
-
)
|
|
209
|
+
mantissa = addWasmI64(WasmI64.extendI32U(digit), mantissa * 10N)
|
|
229
210
|
i += 1n
|
|
230
211
|
numDigitsAfterDot += 1n
|
|
231
212
|
} else if (char == _CHAR_CODE_UNDERSCORE) {
|
|
@@ -242,7 +223,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
242
223
|
numDigits += numDigitsAfterDot
|
|
243
224
|
|
|
244
225
|
match (numDigits) {
|
|
245
|
-
|
|
226
|
+
0n => Err("Invalid float"),
|
|
246
227
|
_ => {
|
|
247
228
|
let _MAX_MANTISSA_DIGITS = 19n // 10^19 fits in uint64
|
|
248
229
|
let _MIN_19DIGIT_INT = 100_0000_0000_0000_0000N
|
|
@@ -266,7 +247,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
266
247
|
Ok(exponentNumber) => {
|
|
267
248
|
let exponentNumber = WasmI32.load(
|
|
268
249
|
WasmI32.fromGrain(exponentNumber),
|
|
269
|
-
|
|
250
|
+
4n
|
|
270
251
|
)
|
|
271
252
|
exponent += exponentNumber
|
|
272
253
|
|
|
@@ -278,14 +259,15 @@ let parseFloatToParts = (string: String) => {
|
|
|
278
259
|
while (i < len) {
|
|
279
260
|
let c = WasmI32.load8U(ptr, i)
|
|
280
261
|
if (c == _CHAR_CODE_DOT || c == _CHAR_CODE_0) {
|
|
262
|
+
use WasmI32.{ (<), (>) }
|
|
281
263
|
let n = c - (_CHAR_CODE_0 - 1n)
|
|
282
|
-
numDigits -= if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
264
|
+
numDigits -= if (n < 0n) {
|
|
265
|
+
0n
|
|
266
|
+
} else if (n > 255n) {
|
|
267
|
+
255n
|
|
268
|
+
} else {
|
|
269
|
+
n
|
|
270
|
+
}
|
|
289
271
|
i += 1n
|
|
290
272
|
} else if (c == _CHAR_CODE_UNDERSCORE) {
|
|
291
273
|
continue
|
|
@@ -296,7 +278,8 @@ let parseFloatToParts = (string: String) => {
|
|
|
296
278
|
|
|
297
279
|
// Attempt to parse 19 digits, the most that can fit in an i64
|
|
298
280
|
let mut digitsParsed = 0n
|
|
299
|
-
|
|
281
|
+
use WasmI32.{ (>) }
|
|
282
|
+
if (numDigits > 0n) {
|
|
300
283
|
manyDigits = true
|
|
301
284
|
mantissa = 0N
|
|
302
285
|
|
|
@@ -306,8 +289,8 @@ let parseFloatToParts = (string: String) => {
|
|
|
306
289
|
let char = WasmI32.load8U(ptr, i)
|
|
307
290
|
let digit = char - _CHAR_CODE_0
|
|
308
291
|
if (digit >= 0n && digit < 10n) {
|
|
309
|
-
mantissa =
|
|
310
|
-
|
|
292
|
+
mantissa = addWasmI64(
|
|
293
|
+
mantissa * 10N,
|
|
311
294
|
WasmI64.extendI32U(digit)
|
|
312
295
|
)
|
|
313
296
|
i += 1n
|
|
@@ -339,8 +322,8 @@ let parseFloatToParts = (string: String) => {
|
|
|
339
322
|
let char = WasmI32.load8U(ptr, i)
|
|
340
323
|
let digit = char - _CHAR_CODE_0
|
|
341
324
|
if (digit < 10n) {
|
|
342
|
-
mantissa =
|
|
343
|
-
|
|
325
|
+
mantissa = addWasmI64(
|
|
326
|
+
mantissa * 10N,
|
|
344
327
|
WasmI64.extendI32U(digit)
|
|
345
328
|
)
|
|
346
329
|
i += 1n
|
|
@@ -365,7 +348,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
365
348
|
WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
366
349
|
negative,
|
|
367
350
|
manyDigits,
|
|
368
|
-
)
|
|
351
|
+
),
|
|
369
352
|
)
|
|
370
353
|
} else {
|
|
371
354
|
Ok(
|
|
@@ -374,7 +357,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
374
357
|
WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
375
358
|
negative,
|
|
376
359
|
manyDigits,
|
|
377
|
-
)
|
|
360
|
+
),
|
|
378
361
|
)
|
|
379
362
|
}
|
|
380
363
|
},
|
|
@@ -388,12 +371,7 @@ let parseFloatToParts = (string: String) => {
|
|
|
388
371
|
|
|
389
372
|
@unsafe
|
|
390
373
|
let parseInfNan = s => {
|
|
391
|
-
|
|
392
|
-
let (-) = WasmI32.sub
|
|
393
|
-
let (<) = WasmI32.ltS
|
|
394
|
-
let (>=) = WasmI32.geS
|
|
395
|
-
let (<=) = WasmI32.leS
|
|
396
|
-
let (==) = WasmI32.eq
|
|
374
|
+
use WasmI32.{ (+), (-), (<), (>=), (<=), (==) }
|
|
397
375
|
|
|
398
376
|
let ptr = WasmI32.fromGrain(s)
|
|
399
377
|
match (WasmI32.load(ptr, 4n)) {
|
|
@@ -448,7 +426,9 @@ let parseInfNan = s => {
|
|
|
448
426
|
) {
|
|
449
427
|
Ok((fpNan(), negative))
|
|
450
428
|
} else if (
|
|
451
|
-
c1 == _CHAR_CODE_i &&
|
|
429
|
+
c1 == _CHAR_CODE_i &&
|
|
430
|
+
c2 == _CHAR_CODE_n &&
|
|
431
|
+
c3 == _CHAR_CODE_f
|
|
452
432
|
) {
|
|
453
433
|
if (len - i == 3n) {
|
|
454
434
|
Ok((fpInf(), negative))
|
|
@@ -497,15 +477,14 @@ let parseInfNan = s => {
|
|
|
497
477
|
}
|
|
498
478
|
|
|
499
479
|
@unsafe
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
)
|
|
507
|
-
|
|
508
|
-
let (<<) = WasmI64.shl
|
|
480
|
+
provide let isFastPath = (
|
|
481
|
+
exponent: WasmI32,
|
|
482
|
+
mantissa: WasmI64,
|
|
483
|
+
negative: Bool,
|
|
484
|
+
manyDigits: Bool,
|
|
485
|
+
) => {
|
|
486
|
+
use WasmI32.{ (<=) }
|
|
487
|
+
use WasmI64.{ (<<) }
|
|
509
488
|
|
|
510
489
|
_MIN_EXPONENT_FAST_PATH <= exponent &&
|
|
511
490
|
exponent <= _MAX_EXPONENT_DISGUISED_FAST_PATH &&
|
|
@@ -514,53 +493,48 @@ export let isFastPath =
|
|
|
514
493
|
}
|
|
515
494
|
|
|
516
495
|
@unsafe
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
496
|
+
provide let parseFloat = (string: String) => {
|
|
497
|
+
use WasmI32.{ (!=), (*) }
|
|
520
498
|
match (parseFloatToParts(string)) {
|
|
521
499
|
Ok((exponent, mantissa, negative, manyDigits)) => {
|
|
522
|
-
|
|
500
|
+
use WasmI64.{ (+), (>) }
|
|
501
|
+
let exponent = WasmI32.load(WasmI32.fromGrain(exponent), 4n)
|
|
523
502
|
let mantissa = WasmI64.load(WasmI32.fromGrain(mantissa), 8n)
|
|
524
503
|
let floatOpt = if (isFastPath(exponent, mantissa, negative, manyDigits)) {
|
|
525
|
-
|
|
504
|
+
use WasmI32.{ (<=) }
|
|
526
505
|
if (exponent <= _MAX_EXPONENT_FAST_PATH) {
|
|
527
506
|
// normal fast path
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
let (<) = WasmI32.leS
|
|
531
|
-
|
|
507
|
+
use WasmF64.{ (/), (*) }
|
|
508
|
+
use WasmI32.{ (<) }
|
|
532
509
|
let mantissa = WasmF64.convertI64U(mantissa)
|
|
533
510
|
let n = if (exponent < 0n) {
|
|
534
|
-
|
|
511
|
+
use WasmI32.{ (*) }
|
|
512
|
+
mantissa / getPowers10FastPath(exponent * -1n)
|
|
535
513
|
} else {
|
|
536
514
|
mantissa * getPowers10FastPath(exponent)
|
|
537
515
|
}
|
|
538
516
|
if (negative) {
|
|
539
|
-
Some(WasmI32.toGrain(newFloat64(n * -1.
|
|
517
|
+
Some(WasmI32.toGrain(newFloat64(n * -1.0W)): Number)
|
|
540
518
|
} else {
|
|
541
519
|
Some(WasmI32.toGrain(newFloat64(n)): Number)
|
|
542
520
|
}
|
|
543
521
|
} else {
|
|
544
522
|
// disguised fast path
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
let (>) = WasmI64.gtS
|
|
523
|
+
use WasmI32.{ (-) }
|
|
524
|
+
use WasmI64.{ (*), (<=) }
|
|
548
525
|
|
|
549
526
|
let shift = exponent - _MAX_EXPONENT_FAST_PATH
|
|
550
527
|
|
|
551
|
-
let mantissa = WasmI64.
|
|
552
|
-
mantissa,
|
|
553
|
-
WasmI64.extendI32U(getPowers10(shift))
|
|
554
|
-
)
|
|
528
|
+
let mantissa = mantissa * WasmI64.extendI32U(getPowers10(shift))
|
|
555
529
|
if (mantissa > _MAX_MANTISSA_FAST_PATH) {
|
|
556
530
|
None
|
|
557
531
|
} else {
|
|
558
|
-
|
|
532
|
+
use WasmF64.{ (*) }
|
|
559
533
|
|
|
560
534
|
let mantissa = WasmF64.convertI64U(mantissa)
|
|
561
535
|
let n = mantissa * getPowers10FastPath(_MAX_EXPONENT_FAST_PATH)
|
|
562
536
|
if (negative) {
|
|
563
|
-
Some(WasmI32.toGrain(newFloat64(n * -1.
|
|
537
|
+
Some(WasmI32.toGrain(newFloat64(n * -1.0W)): Number)
|
|
564
538
|
} else {
|
|
565
539
|
Some(WasmI32.toGrain(newFloat64(n)): Number)
|
|
566
540
|
}
|
|
@@ -573,6 +547,7 @@ export let parseFloat = (string: String) => {
|
|
|
573
547
|
match (floatOpt) {
|
|
574
548
|
Some(n) => Ok(n),
|
|
575
549
|
None => {
|
|
550
|
+
use WasmI32.{ (<), (>=) }
|
|
576
551
|
// From Rust:
|
|
577
552
|
// If significant digits were truncated, then we can have rounding error
|
|
578
553
|
// only if `mantissa + 1` produces a different result. We also avoid
|
|
@@ -581,23 +556,21 @@ export let parseFloat = (string: String) => {
|
|
|
581
556
|
|
|
582
557
|
let mut fp = computeFloat(WasmI64.extendI32S(exponent), mantissa)
|
|
583
558
|
let f = WasmI64.load(WasmI32.fromGrain(fp.f), 8n)
|
|
584
|
-
let e = WasmI32.load(WasmI32.fromGrain(fp.e),
|
|
585
|
-
if (manyDigits &&
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
WasmI64.add(mantissa, 1N)
|
|
589
|
-
)
|
|
559
|
+
let e = WasmI32.load(WasmI32.fromGrain(fp.e), 4n)
|
|
560
|
+
if (manyDigits && e >= 0n) {
|
|
561
|
+
use WasmI64.{ (!=) as neWasmI64 }
|
|
562
|
+
let fp2 = computeFloat(WasmI64.extendI32S(exponent), mantissa + 1N)
|
|
590
563
|
let f2 = WasmI64.load(WasmI32.fromGrain(fp2.f), 8n)
|
|
591
|
-
let e2 = WasmI32.load(WasmI32.fromGrain(fp2.e),
|
|
592
|
-
if (e != e2 ||
|
|
564
|
+
let e2 = WasmI32.load(WasmI32.fromGrain(fp2.e), 4n)
|
|
565
|
+
if (e != e2 || neWasmI64(f, f2)) {
|
|
593
566
|
fp.e = -1l
|
|
594
567
|
}
|
|
595
568
|
}
|
|
596
569
|
|
|
597
570
|
// Unable to correctly round the float using the Eisel-Lemire algorithm.
|
|
598
571
|
// Fallback to a slower, but always correct algorithm.
|
|
599
|
-
let e = WasmI32.load(WasmI32.fromGrain(fp.e),
|
|
600
|
-
if (
|
|
572
|
+
let e = WasmI32.load(WasmI32.fromGrain(fp.e), 4n)
|
|
573
|
+
if (e < 0n) {
|
|
601
574
|
fp = parseLongMantissa(string)
|
|
602
575
|
}
|
|
603
576
|
|
package/runtime/atof/parse.md
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Parse
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Values
|
|
6
|
+
|
|
7
|
+
Functions and constants included in the Parse module.
|
|
8
|
+
|
|
1
9
|
### Parse.**isFastPath**
|
|
2
10
|
|
|
3
11
|
```grain
|
|
4
|
-
isFastPath :
|
|
12
|
+
isFastPath :
|
|
13
|
+
(exponent: WasmI32, mantissa: WasmI64, negative: Bool, manyDigits: Bool) =>
|
|
14
|
+
Bool
|
|
5
15
|
```
|
|
6
16
|
|
|
7
17
|
### Parse.**parseFloat**
|
|
8
18
|
|
|
9
19
|
```grain
|
|
10
|
-
parseFloat : String
|
|
20
|
+
parseFloat : (string: String) => Result<Number, String>
|
|
11
21
|
```
|
|
12
22
|
|