@grain/stdlib 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/array.gr +65 -57
- package/array.md +54 -6
- package/buffer.gr +71 -1
- package/buffer.md +142 -0
- package/bytes.gr +52 -3
- package/bytes.md +117 -0
- package/char.gr +23 -20
- package/char.md +18 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +44 -16
- package/immutablepriorityqueue.md +44 -1
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/int32.gr +39 -37
- package/int32.md +6 -0
- package/int64.gr +39 -37
- package/int64.md +6 -0
- package/list.gr +33 -24
- package/list.md +39 -10
- package/map.gr +19 -28
- package/marshal.gr +4 -4
- package/number.gr +727 -26
- package/number.md +345 -23
- package/option.gr +30 -26
- package/option.md +12 -0
- package/package.json +1 -1
- package/path.gr +787 -0
- package/path.md +727 -0
- package/pervasives.gr +3 -4
- package/pervasives.md +6 -1
- package/priorityqueue.gr +25 -5
- package/priorityqueue.md +30 -0
- package/queue.gr +22 -7
- package/queue.md +18 -1
- package/regex.gr +161 -65
- package/regex.md +70 -0
- package/result.gr +24 -20
- package/result.md +12 -0
- package/runtime/atof/common.gr +198 -0
- package/runtime/atof/common.md +243 -0
- package/runtime/atof/decimal.gr +663 -0
- package/runtime/atof/decimal.md +59 -0
- package/runtime/atof/lemire.gr +264 -0
- package/runtime/atof/lemire.md +6 -0
- package/runtime/atof/parse.gr +615 -0
- package/runtime/atof/parse.md +12 -0
- package/runtime/atof/slow.gr +238 -0
- package/runtime/atof/slow.md +6 -0
- package/runtime/atof/table.gr +2016 -0
- package/runtime/atof/table.md +12 -0
- package/runtime/{stringUtils.gr → atoi/parse.gr} +1 -1
- package/runtime/{stringUtils.md → atoi/parse.md} +1 -1
- package/runtime/bigint.gr +7 -7
- package/runtime/compare.gr +2 -1
- package/runtime/equal.gr +3 -2
- package/runtime/exception.gr +9 -5
- package/runtime/exception.md +8 -2
- package/runtime/gc.gr +2 -1
- package/runtime/malloc.gr +1 -3
- package/runtime/numberUtils.gr +13 -13
- package/runtime/numberUtils.md +6 -0
- package/runtime/numbers.gr +123 -39
- package/runtime/numbers.md +26 -0
- package/runtime/string.gr +4 -2
- package/runtime/unsafe/conv.gr +21 -41
- package/runtime/unsafe/conv.md +0 -3
- package/runtime/unsafe/printWasm.gr +4 -40
- package/runtime/utils/printing.gr +3 -3
- package/set.gr +25 -25
- package/stack.gr +14 -0
- package/stack.md +17 -0
- package/string.gr +313 -39
- package/string.md +99 -0
- package/sys/file.gr +1 -1
- package/sys/time.gr +4 -4
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
### Decimal.**Decimal**
|
|
2
|
+
|
|
3
|
+
```grain
|
|
4
|
+
record Decimal {
|
|
5
|
+
numDigits: Int32,
|
|
6
|
+
decimalPoint: Int32,
|
|
7
|
+
truncated: Bool,
|
|
8
|
+
digits: Bytes,
|
|
9
|
+
}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Decimal.**_DECIMAL_POINT_RANGE**
|
|
13
|
+
|
|
14
|
+
```grain
|
|
15
|
+
_DECIMAL_POINT_RANGE : WasmI32
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Decimal.**tryAddDigit**
|
|
19
|
+
|
|
20
|
+
```grain
|
|
21
|
+
tryAddDigit : (Decimal, WasmI32) -> Void
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Decimal.**round**
|
|
25
|
+
|
|
26
|
+
```grain
|
|
27
|
+
round : Decimal -> WasmI64
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Decimal.**get_TABLE**
|
|
31
|
+
|
|
32
|
+
```grain
|
|
33
|
+
get_TABLE : () -> WasmI32
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Decimal.**get_TABLE_POW5**
|
|
37
|
+
|
|
38
|
+
```grain
|
|
39
|
+
get_TABLE_POW5 : () -> WasmI32
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Decimal.**leftShift**
|
|
43
|
+
|
|
44
|
+
```grain
|
|
45
|
+
leftShift : (Decimal, WasmI32) -> Void
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Decimal.**rightShift**
|
|
49
|
+
|
|
50
|
+
```grain
|
|
51
|
+
rightShift : (Decimal, WasmI32) -> Void
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Decimal.**parseDecimal**
|
|
55
|
+
|
|
56
|
+
```grain
|
|
57
|
+
parseDecimal : String -> Decimal
|
|
58
|
+
```
|
|
59
|
+
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/* grainc-flags --no-pervasives */
|
|
2
|
+
|
|
3
|
+
// This module was based on Rust's dec2flt
|
|
4
|
+
// https://github.com/rust-lang/rust/blob/1cbc45942d5c0f6eb5d94e3b10762ba541958035/library/core/src/num/dec2flt/lemire.rs
|
|
5
|
+
// Rust's MIT license is provided below:
|
|
6
|
+
/*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any
|
|
8
|
+
* person obtaining a copy of this software and associated
|
|
9
|
+
* documentation files (the "Software"), to deal in the
|
|
10
|
+
* Software without restriction, including without
|
|
11
|
+
* limitation the rights to use, copy, modify, merge,
|
|
12
|
+
* publish, distribute, sublicense, and/or sell copies of
|
|
13
|
+
* the Software, and to permit persons to whom the Software
|
|
14
|
+
* is furnished to do so, subject to the following
|
|
15
|
+
* conditions:
|
|
16
|
+
*
|
|
17
|
+
* The above copyright notice and this permission notice
|
|
18
|
+
* shall be included in all copies or substantial portions
|
|
19
|
+
* of the Software.
|
|
20
|
+
*
|
|
21
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
22
|
+
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
23
|
+
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
25
|
+
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
26
|
+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
27
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
28
|
+
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
29
|
+
* DEALINGS IN THE SOFTWARE.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import WasmI32 from "runtime/unsafe/wasmi32"
|
|
33
|
+
import WasmI64 from "runtime/unsafe/wasmi64"
|
|
34
|
+
|
|
35
|
+
import { newInt32, newInt64, newFloat64 } from "runtime/dataStructures"
|
|
36
|
+
import { get_POWERS5 } from "./table"
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
_SMALLEST_POWER_OF_FIVE,
|
|
40
|
+
_LARGEST_POWER_OF_FIVE,
|
|
41
|
+
_INFINITE_POWER,
|
|
42
|
+
_SMALLEST_POWER_OF_TEN,
|
|
43
|
+
_LARGEST_POWER_OF_TEN,
|
|
44
|
+
_MANTISSA_EXPLICIT_BITS_32,
|
|
45
|
+
_MANTISSA_EXPLICIT_BITS_64,
|
|
46
|
+
_MINIMUM_EXPONENT,
|
|
47
|
+
_MIN_EXPONENT_ROUND_TO_EVEN,
|
|
48
|
+
_MAX_EXPONENT_ROUND_TO_EVEN,
|
|
49
|
+
fullMultiplication,
|
|
50
|
+
power,
|
|
51
|
+
BiasedFp,
|
|
52
|
+
fpZero,
|
|
53
|
+
fpInf,
|
|
54
|
+
fpErr,
|
|
55
|
+
} from "./common"
|
|
56
|
+
|
|
57
|
+
primitive (&&): (Bool, Bool) -> Bool = "@and"
|
|
58
|
+
primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
59
|
+
primitive (!): Bool -> Bool = "@not"
|
|
60
|
+
|
|
61
|
+
// From Rust:
|
|
62
|
+
// This will compute or rather approximate w * 5**q and return a pair of 64-bit words
|
|
63
|
+
// approximating the result, with the "high" part corresponding to the most significant
|
|
64
|
+
// bits and the low part corresponding to the least significant bits.
|
|
65
|
+
@unsafe
|
|
66
|
+
let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
|
|
67
|
+
let (==) = WasmI64.eq
|
|
68
|
+
let (&) = WasmI64.and
|
|
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
|
|
76
|
+
|
|
77
|
+
let mask = if (precision < 64N) {
|
|
78
|
+
0xFFFF_FFFF_FFFF_FFFFN >> precision
|
|
79
|
+
} else {
|
|
80
|
+
0xFFFF_FFFF_FFFF_FFFFN
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// From Rust:
|
|
84
|
+
// 5^q < 2^64, then the multiplication always provides an exact value.
|
|
85
|
+
// That means whenever we need to round ties to even, we always have
|
|
86
|
+
// an exact value.
|
|
87
|
+
let index = q - _SMALLEST_POWER_OF_FIVE
|
|
88
|
+
let n = WasmI32.mul(16n, WasmI32.wrapI64(index))
|
|
89
|
+
let lo5 = WasmI64.load(get_POWERS5(), n),
|
|
90
|
+
hi5 = WasmI64.load(get_POWERS5(), WasmI32.add(n, 8n))
|
|
91
|
+
|
|
92
|
+
// From Rust:
|
|
93
|
+
// Only need one multiplication as long as there is 1 zero but
|
|
94
|
+
// in the explicit mantissa bits, +1 for the hidden bit, +1 to
|
|
95
|
+
// determine the rounding direction, +1 for if the computed
|
|
96
|
+
// product has a leading zero.
|
|
97
|
+
let (firstLo, firstHi) = fullMultiplication(w, lo5)
|
|
98
|
+
let mut firstLo = WasmI64.load(WasmI32.fromGrain(firstLo), 8n)
|
|
99
|
+
let mut firstHi = WasmI64.load(WasmI32.fromGrain(firstHi), 8n)
|
|
100
|
+
if ((firstHi & mask) == mask) {
|
|
101
|
+
// From Rust:
|
|
102
|
+
// Need to do a second multiplication to get better precision
|
|
103
|
+
// for the lower product. This will always be exact
|
|
104
|
+
// where q is < 55, since 5^55 < 2^128. If this wraps,
|
|
105
|
+
// then we need to need to round up the hi product.
|
|
106
|
+
let (_, secondHi) = fullMultiplication(w, hi5)
|
|
107
|
+
let secondHi = WasmI64.load(WasmI32.fromGrain(secondHi), 8n)
|
|
108
|
+
firstLo += secondHi
|
|
109
|
+
if (secondHi > firstLo) {
|
|
110
|
+
firstHi += 1N
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
(
|
|
115
|
+
WasmI32.toGrain(newInt64(firstLo)): Int64,
|
|
116
|
+
WasmI32.toGrain(newInt64(firstHi)): Int64,
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Returns the significant bits and a biased binary exponent that can be directly shifted into exponent bits:
|
|
121
|
+
// (u64, i32)
|
|
122
|
+
@unsafe
|
|
123
|
+
export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
|
|
124
|
+
let (==) = WasmI64.eq
|
|
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
|
|
133
|
+
|
|
134
|
+
let w = mantissa
|
|
135
|
+
let q = exponent
|
|
136
|
+
|
|
137
|
+
if (w == 0N || q < _SMALLEST_POWER_OF_TEN) {
|
|
138
|
+
fpZero()
|
|
139
|
+
} else if (q > _LARGEST_POWER_OF_TEN) {
|
|
140
|
+
fpInf()
|
|
141
|
+
} else {
|
|
142
|
+
let lz = WasmI64.clz(w)
|
|
143
|
+
let w = w << lz
|
|
144
|
+
let (lo, hi) = computeProductApprox(q, w, _MANTISSA_EXPLICIT_BITS_64 + 3N)
|
|
145
|
+
let lo = WasmI64.load(WasmI32.fromGrain(lo), 8n)
|
|
146
|
+
let hi = WasmI64.load(WasmI32.fromGrain(hi), 8n)
|
|
147
|
+
// From Rust:
|
|
148
|
+
// If we have failed to approximate w x 5^-q with our 128-bit value.
|
|
149
|
+
// Since the addition of 1 could lead to an overflow which could then
|
|
150
|
+
// round up over the half-way point, this can lead to improper rounding
|
|
151
|
+
// of a float.
|
|
152
|
+
//
|
|
153
|
+
// However, this can only occur if q ∈ [-27, 55]. The upper bound of q
|
|
154
|
+
// is 55 because 5^55 < 2^128, however, this can only happen if 5^q > 2^64,
|
|
155
|
+
// since otherwise the product can be represented in 64-bits, producing
|
|
156
|
+
// an exact result. For negative exponents, rounding-to-even can
|
|
157
|
+
// only occur if 5^-q < 2^64.
|
|
158
|
+
//
|
|
159
|
+
// For detailed explanations of rounding for negative exponents, see
|
|
160
|
+
// <https://arxiv.org/pdf/2101.11408.pdf#section.9.1>. For detailed
|
|
161
|
+
// explanations of rounding for positive exponents, see
|
|
162
|
+
// <https://arxiv.org/pdf/2101.11408.pdf#section.8>.
|
|
163
|
+
match (lo == 0xFFFF_FFFF_FFFF_FFFFN && !(q >= -27N && q <= 55N)) {
|
|
164
|
+
true => fpErr(),
|
|
165
|
+
false => {
|
|
166
|
+
let upperbit = WasmI32.wrapI64(WasmI64.shrU(hi, 63N))
|
|
167
|
+
let mut mantissa = WasmI64.shrU(
|
|
168
|
+
hi,
|
|
169
|
+
WasmI64.extendI32S(
|
|
170
|
+
{
|
|
171
|
+
let (+) = WasmI32.add
|
|
172
|
+
let (-) = WasmI32.sub
|
|
173
|
+
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
let mut power2 = {
|
|
178
|
+
let (+) = WasmI32.add
|
|
179
|
+
let (-) = WasmI32.sub
|
|
180
|
+
let q = WasmI32.wrapI64(q)
|
|
181
|
+
let lz = WasmI32.wrapI64(lz)
|
|
182
|
+
power(q) + upperbit - lz - _MINIMUM_EXPONENT
|
|
183
|
+
}
|
|
184
|
+
if (WasmI32.leS(power2, 0n)) {
|
|
185
|
+
// -power2 + 1 >= 64
|
|
186
|
+
if (WasmI32.geS(WasmI32.add(WasmI32.mul(-1n, power2), 1n), 64n)) {
|
|
187
|
+
// Have more than 64 bits below the minimum exponent, must be 0.
|
|
188
|
+
fpZero()
|
|
189
|
+
} else {
|
|
190
|
+
// Have a subnormal value.
|
|
191
|
+
mantissa = mantissa >>
|
|
192
|
+
WasmI64.extendI32S(WasmI32.add(WasmI32.mul(-1n, power2), 1n))
|
|
193
|
+
mantissa += mantissa & 1N
|
|
194
|
+
mantissa = mantissa >> 1N
|
|
195
|
+
power2 = if (mantissa >= 1N << _MANTISSA_EXPLICIT_BITS_64) {
|
|
196
|
+
1n
|
|
197
|
+
} else {
|
|
198
|
+
0n
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
{
|
|
202
|
+
f: WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
203
|
+
e: WasmI32.toGrain(newInt32(power2)): Int32,
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// Need to handle rounding ties. Normally, we need to round up,
|
|
208
|
+
// but if we fall right in between and and we have an even basis, we
|
|
209
|
+
// need to round down.
|
|
210
|
+
//
|
|
211
|
+
// This will only occur if:
|
|
212
|
+
// 1. The lower 64 bits of the 128-bit representation is 0.
|
|
213
|
+
// IE, 5^q fits in single 64-bit word.
|
|
214
|
+
// 2. The least-significant bit prior to truncated mantissa is odd.
|
|
215
|
+
// 3. All the bits truncated when shifting to mantissa bits + 1 are 0.
|
|
216
|
+
//
|
|
217
|
+
// Or, we may fall between two floats: we are exactly halfway.
|
|
218
|
+
if (
|
|
219
|
+
WasmI64.leU(lo, 1N) &&
|
|
220
|
+
q >= _MIN_EXPONENT_ROUND_TO_EVEN &&
|
|
221
|
+
q <= _MAX_EXPONENT_ROUND_TO_EVEN &&
|
|
222
|
+
(mantissa & 3N) == 1N &&
|
|
223
|
+
mantissa <<
|
|
224
|
+
WasmI64.extendI32S(
|
|
225
|
+
{
|
|
226
|
+
let (+) = WasmI32.add
|
|
227
|
+
let (-) = WasmI32.sub
|
|
228
|
+
upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
|
|
229
|
+
}
|
|
230
|
+
) ==
|
|
231
|
+
hi
|
|
232
|
+
) {
|
|
233
|
+
// Zero the lowest bit, so we don't round up.
|
|
234
|
+
// mantissa &= !1N;
|
|
235
|
+
mantissa = mantissa & WasmI64.xor(1N, -1N)
|
|
236
|
+
}
|
|
237
|
+
// Round-to-even, then shift the significant digits into place.
|
|
238
|
+
mantissa += mantissa & 1N
|
|
239
|
+
mantissa = WasmI64.shrU(mantissa, 1N)
|
|
240
|
+
if (WasmI64.geU(mantissa, 2N << _MANTISSA_EXPLICIT_BITS_64)) {
|
|
241
|
+
// Rounding up overflowed, so the carry bit is set. Set the
|
|
242
|
+
// mantissa to 1 (only the implicit, hidden bit is set) and
|
|
243
|
+
// increase the exponent.
|
|
244
|
+
mantissa = 1N << _MANTISSA_EXPLICIT_BITS_64
|
|
245
|
+
power2 = WasmI32.add(power2, 1n)
|
|
246
|
+
}
|
|
247
|
+
// Zero out the hidden bit.
|
|
248
|
+
mantissa = mantissa &
|
|
249
|
+
WasmI64.xor(1N << _MANTISSA_EXPLICIT_BITS_64, -1N)
|
|
250
|
+
if (WasmI32.geS(power2, _INFINITE_POWER)) {
|
|
251
|
+
// Exponent is above largest normal value, must be infinite.
|
|
252
|
+
fpInf()
|
|
253
|
+
} else {
|
|
254
|
+
|
|
255
|
+
{
|
|
256
|
+
f: WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
257
|
+
e: WasmI32.toGrain(newInt32(power2)): Int32,
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|