@grain/stdlib 0.5.4 → 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.
Files changed (59) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/array.gr +60 -57
  3. package/array.md +24 -6
  4. package/buffer.gr +71 -1
  5. package/buffer.md +142 -0
  6. package/bytes.gr +52 -3
  7. package/bytes.md +117 -0
  8. package/char.gr +21 -18
  9. package/char.md +18 -3
  10. package/immutablepriorityqueue.gr +13 -13
  11. package/int32.gr +39 -37
  12. package/int32.md +6 -0
  13. package/int64.gr +39 -37
  14. package/int64.md +6 -0
  15. package/list.gr +31 -22
  16. package/list.md +39 -10
  17. package/map.gr +19 -28
  18. package/number.gr +81 -5
  19. package/number.md +64 -2
  20. package/option.gr +30 -26
  21. package/option.md +12 -0
  22. package/package.json +1 -1
  23. package/path.gr +787 -0
  24. package/path.md +727 -0
  25. package/pervasives.gr +3 -4
  26. package/pervasives.md +6 -1
  27. package/queue.gr +11 -9
  28. package/queue.md +2 -0
  29. package/regex.gr +76 -3
  30. package/regex.md +70 -0
  31. package/result.gr +24 -20
  32. package/result.md +12 -0
  33. package/runtime/atof/common.gr +198 -0
  34. package/runtime/atof/common.md +243 -0
  35. package/runtime/atof/decimal.gr +663 -0
  36. package/runtime/atof/decimal.md +59 -0
  37. package/runtime/atof/lemire.gr +264 -0
  38. package/runtime/atof/lemire.md +6 -0
  39. package/runtime/atof/parse.gr +615 -0
  40. package/runtime/atof/parse.md +12 -0
  41. package/runtime/atof/slow.gr +238 -0
  42. package/runtime/atof/slow.md +6 -0
  43. package/runtime/atof/table.gr +2016 -0
  44. package/runtime/atof/table.md +12 -0
  45. package/runtime/{stringUtils.gr → atoi/parse.gr} +1 -1
  46. package/runtime/{stringUtils.md → atoi/parse.md} +1 -1
  47. package/runtime/bigint.gr +3 -3
  48. package/runtime/equal.gr +1 -1
  49. package/runtime/numberUtils.gr +2 -2
  50. package/runtime/numberUtils.md +6 -0
  51. package/runtime/numbers.gr +4 -4
  52. package/runtime/unsafe/conv.gr +21 -41
  53. package/runtime/unsafe/conv.md +0 -3
  54. package/runtime/unsafe/printWasm.gr +4 -40
  55. package/runtime/utils/printing.gr +3 -3
  56. package/stack.gr +4 -2
  57. package/stack.md +2 -0
  58. package/string.gr +1 -1
  59. 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
+ }
@@ -0,0 +1,6 @@
1
+ ### Lemire.**computeFloat**
2
+
3
+ ```grain
4
+ computeFloat : (WasmI64, WasmI64) -> %Common.BiasedFp
5
+ ```
6
+