@grain/stdlib 0.5.12 → 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 +200 -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/random.gr
CHANGED
|
@@ -1,58 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Pseudo-random number generation.
|
|
3
|
+
*
|
|
4
|
+
* @example from "random" include Random
|
|
5
|
+
*
|
|
4
6
|
* @since v0.5.0
|
|
5
7
|
*/
|
|
6
|
-
|
|
7
|
-
import Result from "result"
|
|
8
|
-
import Int32 from "int32"
|
|
9
|
-
import Int64 from "int64"
|
|
10
|
-
import WasmI32 from "runtime/unsafe/wasmi32"
|
|
11
|
-
import WasmI64 from "runtime/unsafe/wasmi64"
|
|
12
|
-
import Memory from "runtime/unsafe/memory"
|
|
13
|
-
import DS from "runtime/dataStructures"
|
|
8
|
+
module Random
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
from "wasi/random" include Random as WasiRandom
|
|
11
|
+
from "result" include Result
|
|
12
|
+
from "uint32" include Uint32
|
|
13
|
+
from "uint64" include Uint64
|
|
14
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
15
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
16
|
+
from "runtime/unsafe/memory" include Memory
|
|
17
|
+
from "runtime/dataStructures" include DataStructures as DS
|
|
18
18
|
|
|
19
|
-
record Random {
|
|
20
|
-
seed:
|
|
21
|
-
mut counter:
|
|
19
|
+
abstract record Random {
|
|
20
|
+
seed: Uint64,
|
|
21
|
+
mut counter: Uint64,
|
|
22
22
|
mut initialized: Bool,
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* @section Values: Functions for working with pseudo-random number generators.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
25
|
let incCounter = random => {
|
|
30
|
-
random.counter =
|
|
26
|
+
random.counter = Uint64.incr(random.counter)
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
// https://arxiv.org/pdf/2004.06278v3.pdf
|
|
34
30
|
@unsafe
|
|
35
|
-
let squares = (ctr:
|
|
31
|
+
let squares = (ctr: Uint64, key: Uint64) => {
|
|
32
|
+
use WasmI64.{ (+), (*), (|), (<<), (>>>) }
|
|
36
33
|
// Implemented with @unsafe to boost efficiency
|
|
37
34
|
// and have fine-grained control over overflow semantics
|
|
38
35
|
let ctr = WasmI64.load(WasmI32.fromGrain(ctr), 8n)
|
|
39
36
|
let key = WasmI64.load(WasmI32.fromGrain(key), 8n)
|
|
40
|
-
let mut x =
|
|
37
|
+
let mut x = ctr * key
|
|
41
38
|
let mut y = x
|
|
42
|
-
let mut z =
|
|
39
|
+
let mut z = y + key
|
|
43
40
|
// round 1
|
|
44
|
-
x =
|
|
45
|
-
x =
|
|
41
|
+
x = x * x + y
|
|
42
|
+
x = x >>> 32N | x << 32N
|
|
46
43
|
// round 2
|
|
47
|
-
x =
|
|
48
|
-
x =
|
|
44
|
+
x = x * x + z
|
|
45
|
+
x = x >>> 32N | x << 32N
|
|
49
46
|
// round 3
|
|
50
|
-
x =
|
|
51
|
-
x =
|
|
52
|
-
let ret = WasmI32.wrapI64(
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
WasmI32.toGrain(DS.newInt32(ret)): Int32
|
|
47
|
+
x = x * x + y
|
|
48
|
+
x = x >>> 32N | x << 32N
|
|
49
|
+
let ret = WasmI32.wrapI64((x * x + z) >>> 32N)
|
|
50
|
+
WasmI32.toGrain(DS.newUint32(ret)): Uint32
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
/**
|
|
@@ -63,8 +58,8 @@ let squares = (ctr: Int64, key: Int64) => {
|
|
|
63
58
|
*
|
|
64
59
|
* @since v0.5.0
|
|
65
60
|
*/
|
|
66
|
-
|
|
67
|
-
{ seed, counter:
|
|
61
|
+
provide let make = seed => {
|
|
62
|
+
{ seed, counter: 0uL, initialized: false }
|
|
68
63
|
}
|
|
69
64
|
|
|
70
65
|
/**
|
|
@@ -74,11 +69,11 @@ export let make = seed => {
|
|
|
74
69
|
*
|
|
75
70
|
* @since v0.5.0
|
|
76
71
|
*/
|
|
77
|
-
|
|
72
|
+
provide let makeUnseeded = () => {
|
|
78
73
|
// TODO: Should we just .expect this result for UX's sake?
|
|
79
74
|
Result.map(seed => {
|
|
80
|
-
{ seed, counter:
|
|
81
|
-
}, WasiRandom.
|
|
75
|
+
{ seed, counter: 0uL, initialized: false }
|
|
76
|
+
}, WasiRandom.randomUint64())
|
|
82
77
|
}
|
|
83
78
|
|
|
84
79
|
/**
|
|
@@ -91,8 +86,10 @@ export let makeUnseeded = () => {
|
|
|
91
86
|
* we do another increment at the end.
|
|
92
87
|
*/
|
|
93
88
|
let checkInitialized = (random: Random) => {
|
|
89
|
+
use Uint32.*
|
|
90
|
+
|
|
94
91
|
if (!random.initialized) {
|
|
95
|
-
while (
|
|
92
|
+
while (clz(squares(random.counter, random.seed)) > 0ul) {
|
|
96
93
|
incCounter(random)
|
|
97
94
|
}
|
|
98
95
|
// now that it's initialized, increment it again to make it a little more random
|
|
@@ -107,9 +104,10 @@ let checkInitialized = (random: Random) => {
|
|
|
107
104
|
* @param random: The pseudo-random number generator to use
|
|
108
105
|
* @returns The randomly generated number
|
|
109
106
|
*
|
|
110
|
-
* @since v0.
|
|
107
|
+
* @since v0.6.0
|
|
108
|
+
* @history v0.5.0: Originally named `nextInt32`
|
|
111
109
|
*/
|
|
112
|
-
|
|
110
|
+
provide let nextUint32 = (random: Random) => {
|
|
113
111
|
checkInitialized(random)
|
|
114
112
|
let ret = squares(random.counter, random.seed)
|
|
115
113
|
incCounter(random)
|
|
@@ -122,19 +120,21 @@ export let nextInt32 = (random: Random) => {
|
|
|
122
120
|
* @param random: The pseudo-random number generator to use
|
|
123
121
|
* @returns The randomly generated number
|
|
124
122
|
*
|
|
125
|
-
* @since v0.
|
|
123
|
+
* @since v0.6.0
|
|
124
|
+
* @history v0.5.0: Originally named `nextInt64`
|
|
126
125
|
*/
|
|
127
|
-
|
|
126
|
+
provide let nextUint64 = (random: Random) => {
|
|
127
|
+
use Uint64.{ (|), (<<) }
|
|
128
128
|
checkInitialized(random)
|
|
129
|
-
let ret1 =
|
|
130
|
-
|
|
129
|
+
let ret1 = Uint64.fromNumber(
|
|
130
|
+
Uint32.toNumber(squares(random.counter, random.seed))
|
|
131
131
|
)
|
|
132
132
|
incCounter(random)
|
|
133
|
-
let ret2 =
|
|
134
|
-
|
|
133
|
+
let ret2 = Uint64.fromNumber(
|
|
134
|
+
Uint32.toNumber(squares(random.counter, random.seed))
|
|
135
135
|
)
|
|
136
136
|
incCounter(random)
|
|
137
|
-
|
|
137
|
+
ret1 << 32uL | ret2
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
/**
|
|
@@ -146,23 +146,19 @@ export let nextInt64 = (random: Random) => {
|
|
|
146
146
|
* @param high: The upper bound of the range (exclusive)
|
|
147
147
|
* @returns The randomly generated number
|
|
148
148
|
*
|
|
149
|
-
* @since v0.
|
|
149
|
+
* @since v0.6.0
|
|
150
|
+
* @history v0.5.0: Originally named `nextInt32InRange`
|
|
150
151
|
*/
|
|
151
|
-
|
|
152
|
+
provide let nextUint32InRange = (random: Random, low: Uint32, high: Uint32) => {
|
|
152
153
|
// Algorithm source: https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method
|
|
153
|
-
|
|
154
|
-
let
|
|
155
|
-
let (
|
|
156
|
-
let (
|
|
157
|
-
let
|
|
158
|
-
let (>) = Int32.gtU
|
|
159
|
-
let range = high - low - 1l
|
|
160
|
-
let mask = Int32.shrU(Int32.lnot(0l), Int32.clz(Int32.lor(range, 1l)))
|
|
161
|
-
let mut x = nextInt32(random) & mask
|
|
162
|
-
let mut iters = 0l
|
|
154
|
+
use Uint32.*
|
|
155
|
+
let range = high - low - 1ul
|
|
156
|
+
let mask = lnot(0ul) >>> clz(range | 1ul)
|
|
157
|
+
let mut x = nextUint32(random) & mask
|
|
158
|
+
let mut iters = 0ul
|
|
163
159
|
while (x > range) {
|
|
164
|
-
x =
|
|
165
|
-
iters +=
|
|
160
|
+
x = nextUint32(random) & mask
|
|
161
|
+
iters += 1ul
|
|
166
162
|
}
|
|
167
163
|
x + low
|
|
168
164
|
}
|
|
@@ -176,21 +172,17 @@ export let nextInt32InRange = (random: Random, low: Int32, high: Int32) => {
|
|
|
176
172
|
* @param high: The upper bound of the range (exclusive)
|
|
177
173
|
* @returns The randomly generated number
|
|
178
174
|
*
|
|
179
|
-
* @since v0.
|
|
175
|
+
* @since v0.6.0
|
|
176
|
+
* @history v0.5.0: Originally named `nextInt64InRange`
|
|
180
177
|
*/
|
|
181
|
-
|
|
178
|
+
provide let nextUint64InRange = (random: Random, low: Uint64, high: Uint64) => {
|
|
182
179
|
// Algorithm source: https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method
|
|
183
|
-
|
|
184
|
-
let
|
|
185
|
-
let (
|
|
186
|
-
let (
|
|
187
|
-
let (&) = Int64.land
|
|
188
|
-
let (>) = Int64.gtU
|
|
189
|
-
let range = high - low - 1L
|
|
190
|
-
let mask = Int64.shrU(Int64.lnot(0L), Int64.clz(Int64.lor(range, 1L)))
|
|
191
|
-
let mut x = nextInt64(random) & mask
|
|
180
|
+
use Uint64.*
|
|
181
|
+
let range = high - low - 1uL
|
|
182
|
+
let mask = lnot(0uL) >>> clz(range | 1uL)
|
|
183
|
+
let mut x = nextUint64(random) & mask
|
|
192
184
|
while (x > range) {
|
|
193
|
-
x =
|
|
185
|
+
x = nextUint64(random) & mask
|
|
194
186
|
}
|
|
195
187
|
x + low
|
|
196
188
|
}
|
package/random.md
CHANGED
|
@@ -10,7 +10,7 @@ No other changes yet.
|
|
|
10
10
|
</details>
|
|
11
11
|
|
|
12
12
|
```grain
|
|
13
|
-
|
|
13
|
+
from "random" include Random
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Types
|
|
@@ -25,7 +25,7 @@ type Random
|
|
|
25
25
|
|
|
26
26
|
## Values
|
|
27
27
|
|
|
28
|
-
Functions
|
|
28
|
+
Functions and constants included in the Random module.
|
|
29
29
|
|
|
30
30
|
### Random.**make**
|
|
31
31
|
|
|
@@ -35,7 +35,7 @@ No other changes yet.
|
|
|
35
35
|
</details>
|
|
36
36
|
|
|
37
37
|
```grain
|
|
38
|
-
make :
|
|
38
|
+
make : (seed: Uint64) => Random
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Creates a new pseudo-random number generator with the given seed.
|
|
@@ -44,7 +44,7 @@ Parameters:
|
|
|
44
44
|
|
|
45
45
|
|param|type|description|
|
|
46
46
|
|-----|----|-----------|
|
|
47
|
-
|`seed`|`
|
|
47
|
+
|`seed`|`Uint64`|The seed for the pseudo-random number generator|
|
|
48
48
|
|
|
49
49
|
Returns:
|
|
50
50
|
|
|
@@ -60,7 +60,7 @@ No other changes yet.
|
|
|
60
60
|
</details>
|
|
61
61
|
|
|
62
62
|
```grain
|
|
63
|
-
makeUnseeded : ()
|
|
63
|
+
makeUnseeded : () => Result<Random, Exception>
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
Creates a new pseudo-random number generator with a random seed.
|
|
@@ -71,15 +71,22 @@ Returns:
|
|
|
71
71
|
|----|-----------|
|
|
72
72
|
|`Result<Random, Exception>`|`Ok(generator)` of a pseudo-random number generator if successful or `Err(exception)` otherwise|
|
|
73
73
|
|
|
74
|
-
### Random.**
|
|
75
|
-
|
|
76
|
-
<details
|
|
77
|
-
<summary
|
|
78
|
-
|
|
74
|
+
### Random.**nextUint32**
|
|
75
|
+
|
|
76
|
+
<details>
|
|
77
|
+
<summary>Added in <code>0.6.0</code></summary>
|
|
78
|
+
<table>
|
|
79
|
+
<thead>
|
|
80
|
+
<tr><th>version</th><th>changes</th></tr>
|
|
81
|
+
</thead>
|
|
82
|
+
<tbody>
|
|
83
|
+
<tr><td><code>0.5.0</code></td><td>Originally named `nextInt32`</td></tr>
|
|
84
|
+
</tbody>
|
|
85
|
+
</table>
|
|
79
86
|
</details>
|
|
80
87
|
|
|
81
88
|
```grain
|
|
82
|
-
|
|
89
|
+
nextUint32 : (random: Random) => Uint32
|
|
83
90
|
```
|
|
84
91
|
|
|
85
92
|
Generates a random 32-bit integer from the given pseudo-random number generator.
|
|
@@ -94,17 +101,24 @@ Returns:
|
|
|
94
101
|
|
|
95
102
|
|type|description|
|
|
96
103
|
|----|-----------|
|
|
97
|
-
|`
|
|
98
|
-
|
|
99
|
-
### Random.**
|
|
100
|
-
|
|
101
|
-
<details
|
|
102
|
-
<summary
|
|
103
|
-
|
|
104
|
+
|`Uint32`|The randomly generated number|
|
|
105
|
+
|
|
106
|
+
### Random.**nextUint64**
|
|
107
|
+
|
|
108
|
+
<details>
|
|
109
|
+
<summary>Added in <code>0.6.0</code></summary>
|
|
110
|
+
<table>
|
|
111
|
+
<thead>
|
|
112
|
+
<tr><th>version</th><th>changes</th></tr>
|
|
113
|
+
</thead>
|
|
114
|
+
<tbody>
|
|
115
|
+
<tr><td><code>0.5.0</code></td><td>Originally named `nextInt64`</td></tr>
|
|
116
|
+
</tbody>
|
|
117
|
+
</table>
|
|
104
118
|
</details>
|
|
105
119
|
|
|
106
120
|
```grain
|
|
107
|
-
|
|
121
|
+
nextUint64 : (random: Random) => Uint64
|
|
108
122
|
```
|
|
109
123
|
|
|
110
124
|
Generates a random 64-bit integer from the given pseudo-random number generator.
|
|
@@ -119,17 +133,24 @@ Returns:
|
|
|
119
133
|
|
|
120
134
|
|type|description|
|
|
121
135
|
|----|-----------|
|
|
122
|
-
|`
|
|
123
|
-
|
|
124
|
-
### Random.**
|
|
125
|
-
|
|
126
|
-
<details
|
|
127
|
-
<summary
|
|
128
|
-
|
|
136
|
+
|`Uint64`|The randomly generated number|
|
|
137
|
+
|
|
138
|
+
### Random.**nextUint32InRange**
|
|
139
|
+
|
|
140
|
+
<details>
|
|
141
|
+
<summary>Added in <code>0.6.0</code></summary>
|
|
142
|
+
<table>
|
|
143
|
+
<thead>
|
|
144
|
+
<tr><th>version</th><th>changes</th></tr>
|
|
145
|
+
</thead>
|
|
146
|
+
<tbody>
|
|
147
|
+
<tr><td><code>0.5.0</code></td><td>Originally named `nextInt32InRange`</td></tr>
|
|
148
|
+
</tbody>
|
|
149
|
+
</table>
|
|
129
150
|
</details>
|
|
130
151
|
|
|
131
152
|
```grain
|
|
132
|
-
|
|
153
|
+
nextUint32InRange : (random: Random, low: Uint32, high: Uint32) => Uint32
|
|
133
154
|
```
|
|
134
155
|
|
|
135
156
|
Generates a random 32-bit integer from the given pseudo-random number generator
|
|
@@ -140,24 +161,31 @@ Parameters:
|
|
|
140
161
|
|param|type|description|
|
|
141
162
|
|-----|----|-----------|
|
|
142
163
|
|`random`|`Random`|The pseudo-random number generator to use|
|
|
143
|
-
|`low`|`
|
|
144
|
-
|`high`|`
|
|
164
|
+
|`low`|`Uint32`|The lower bound of the range (inclusive)|
|
|
165
|
+
|`high`|`Uint32`|The upper bound of the range (exclusive)|
|
|
145
166
|
|
|
146
167
|
Returns:
|
|
147
168
|
|
|
148
169
|
|type|description|
|
|
149
170
|
|----|-----------|
|
|
150
|
-
|`
|
|
151
|
-
|
|
152
|
-
### Random.**
|
|
153
|
-
|
|
154
|
-
<details
|
|
155
|
-
<summary
|
|
156
|
-
|
|
171
|
+
|`Uint32`|The randomly generated number|
|
|
172
|
+
|
|
173
|
+
### Random.**nextUint64InRange**
|
|
174
|
+
|
|
175
|
+
<details>
|
|
176
|
+
<summary>Added in <code>0.6.0</code></summary>
|
|
177
|
+
<table>
|
|
178
|
+
<thead>
|
|
179
|
+
<tr><th>version</th><th>changes</th></tr>
|
|
180
|
+
</thead>
|
|
181
|
+
<tbody>
|
|
182
|
+
<tr><td><code>0.5.0</code></td><td>Originally named `nextInt64InRange`</td></tr>
|
|
183
|
+
</tbody>
|
|
184
|
+
</table>
|
|
157
185
|
</details>
|
|
158
186
|
|
|
159
187
|
```grain
|
|
160
|
-
|
|
188
|
+
nextUint64InRange : (random: Random, low: Uint64, high: Uint64) => Uint64
|
|
161
189
|
```
|
|
162
190
|
|
|
163
191
|
Generates a random 64-bit integer from the given pseudo-random number generator
|
|
@@ -168,12 +196,12 @@ Parameters:
|
|
|
168
196
|
|param|type|description|
|
|
169
197
|
|-----|----|-----------|
|
|
170
198
|
|`random`|`Random`|The pseudo-random number generator to use|
|
|
171
|
-
|`low`|`
|
|
172
|
-
|`high`|`
|
|
199
|
+
|`low`|`Uint64`|The lower bound of the range (inclusive)|
|
|
200
|
+
|`high`|`Uint64`|The upper bound of the range (exclusive)|
|
|
173
201
|
|
|
174
202
|
Returns:
|
|
175
203
|
|
|
176
204
|
|type|description|
|
|
177
205
|
|----|-----------|
|
|
178
|
-
|`
|
|
206
|
+
|`Uint64`|The randomly generated number|
|
|
179
207
|
|
package/range.gr
CHANGED
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Utilities for working with ranges.
|
|
3
|
+
*
|
|
4
|
+
* A range represents an interval—a set of values with a beginning and an end.
|
|
5
|
+
*
|
|
6
|
+
* All functions in this module treat ranges as exclusive, but inclusive versions
|
|
7
|
+
* of all APIs are available in the `Inclusive` submodule.
|
|
8
|
+
*
|
|
9
|
+
* @example from "range" include Range
|
|
10
|
+
*
|
|
4
11
|
* @since v0.3.0
|
|
12
|
+
* @history v0.6.0: Treats all ranges as exclusive
|
|
5
13
|
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @section Types: Type declarations included in the Range module.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Ranges can be inclusive or exclusive. When `Inclusive`, the end value will be included in operations. When `Exclusive`, the end value will be excluded from operations.
|
|
13
|
-
*/
|
|
14
|
-
export enum Range {
|
|
15
|
-
Inclusive(Number, Number),
|
|
16
|
-
Exclusive(Number, Number),
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @section Values: Functions and constants included in the Range module.
|
|
21
|
-
*/
|
|
14
|
+
module Range
|
|
22
15
|
|
|
23
16
|
/**
|
|
24
17
|
* Checks if the given number is within the range.
|
|
@@ -27,55 +20,47 @@ export enum Range {
|
|
|
27
20
|
* @param range: The range to check within
|
|
28
21
|
* @returns Whether or not the value is within range
|
|
29
22
|
*
|
|
30
|
-
* @example Range.inRange(1,
|
|
31
|
-
* @example Range.inRange(10,
|
|
23
|
+
* @example Range.inRange(1, { rangeStart: 0, rangeEnd: 2 }) == true
|
|
24
|
+
* @example Range.inRange(10, { rangeStart: 0, rangeEnd: 2 }) == false
|
|
32
25
|
*
|
|
33
26
|
* @since v0.3.0
|
|
27
|
+
* @history v0.6.0: Treats all ranges as exclusive
|
|
34
28
|
*/
|
|
35
|
-
|
|
29
|
+
provide let inRange = (value, range) => {
|
|
36
30
|
match (range) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
{ rangeStart: lower, rangeEnd: upper } when value >= lower && value < upper =>
|
|
32
|
+
true,
|
|
33
|
+
{ rangeStart: upper, rangeEnd: lower } when value >= lower && value < upper =>
|
|
34
|
+
true,
|
|
41
35
|
_ => false,
|
|
42
36
|
}
|
|
43
37
|
}
|
|
44
38
|
|
|
45
39
|
/**
|
|
46
|
-
* Calls the given function with each number in the range.
|
|
40
|
+
* Calls the given function with each number in the range.
|
|
41
|
+
*
|
|
42
|
+
* For increasing ranges, the value is increased by `1` in each iteration,
|
|
43
|
+
* and for decreasing ranges, the value is decreased by `1`. The value is
|
|
44
|
+
* always changed by `1`, even if non-integer values were provided in the range.
|
|
47
45
|
*
|
|
48
46
|
* @param fn: The function to be executed on each number in the range
|
|
49
47
|
* @param range: The range to iterate
|
|
50
48
|
*
|
|
51
|
-
* @example Range.forEach(val => print(val),
|
|
49
|
+
* @example Range.forEach(val => print(val), { rangeStart: 0, rangeEnd: 2 })
|
|
52
50
|
*
|
|
53
51
|
* @since v0.3.0
|
|
52
|
+
* @history v0.6.0: Treats all ranges as exclusive
|
|
54
53
|
*/
|
|
55
|
-
|
|
54
|
+
provide let forEach = (fn: Number => Void, range) => {
|
|
56
55
|
match (range) {
|
|
57
|
-
|
|
58
|
-
let mut idx = lower
|
|
59
|
-
while (idx <= upper) {
|
|
60
|
-
fn(idx)
|
|
61
|
-
idx += 1
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
Inclusive(upper, lower) => {
|
|
65
|
-
let mut idx = upper
|
|
66
|
-
while (idx >= lower) {
|
|
67
|
-
fn(idx)
|
|
68
|
-
idx -= 1
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
Exclusive(lower, upper) when lower <= upper => {
|
|
56
|
+
{ rangeStart: lower, rangeEnd: upper } when lower <= upper => {
|
|
72
57
|
let mut idx = lower
|
|
73
58
|
while (idx < upper) {
|
|
74
59
|
fn(idx)
|
|
75
60
|
idx += 1
|
|
76
61
|
}
|
|
77
62
|
},
|
|
78
|
-
|
|
63
|
+
{ rangeStart: upper, rangeEnd: lower } => {
|
|
79
64
|
let mut idx = upper
|
|
80
65
|
while (idx > lower) {
|
|
81
66
|
fn(idx)
|
|
@@ -86,41 +71,32 @@ export let forEach = (fn: Number -> Void, range) => {
|
|
|
86
71
|
}
|
|
87
72
|
|
|
88
73
|
/**
|
|
89
|
-
* Produces a list by calling the given function on each number included in the range.
|
|
74
|
+
* Produces a list by calling the given function on each number included in the range.
|
|
75
|
+
*
|
|
76
|
+
* For increasing ranges, the value is increased by `1` in each iteration,
|
|
77
|
+
* and for decreasing ranges, the value is decreased by `1`. The value is
|
|
78
|
+
* always changed by `1`, even if non-integer values were provided in the range.
|
|
90
79
|
*
|
|
91
80
|
* @param fn: The function called on each number in the range that returns the value for the output list
|
|
92
81
|
* @param range: The range to iterate
|
|
93
82
|
* @returns A list containing all values returned from the `fn`
|
|
94
83
|
*
|
|
95
|
-
* @example Range.map(val => val * 2,
|
|
84
|
+
* @example Range.map(val => val * 2, { rangeStart: 0, rangeEnd: 3 }) == [0, 2, 4]
|
|
96
85
|
*
|
|
97
86
|
* @since v0.3.2
|
|
87
|
+
* @history v0.6.0: Treats all ranges as exclusive
|
|
98
88
|
*/
|
|
99
|
-
|
|
89
|
+
provide let map = (fn, range) => {
|
|
100
90
|
let mut result = []
|
|
101
91
|
match (range) {
|
|
102
|
-
|
|
103
|
-
let mut idx = upper
|
|
104
|
-
while (idx >= lower) {
|
|
105
|
-
result = [fn(idx), ...result]
|
|
106
|
-
idx -= 1
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
Inclusive(upper, lower) => {
|
|
110
|
-
let mut idx = lower
|
|
111
|
-
while (idx <= upper) {
|
|
112
|
-
result = [fn(idx), ...result]
|
|
113
|
-
idx += 1
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
Exclusive(lower, upper) when lower <= upper => {
|
|
92
|
+
{ rangeStart: lower, rangeEnd: upper } when lower <= upper => {
|
|
117
93
|
let mut idx = upper - 1
|
|
118
94
|
while (idx >= lower) {
|
|
119
95
|
result = [fn(idx), ...result]
|
|
120
96
|
idx -= 1
|
|
121
97
|
}
|
|
122
98
|
},
|
|
123
|
-
|
|
99
|
+
{ rangeStart: upper, rangeEnd: lower } => {
|
|
124
100
|
let mut idx = lower + 1
|
|
125
101
|
while (idx <= upper) {
|
|
126
102
|
result = [fn(idx), ...result]
|
|
@@ -130,3 +106,99 @@ export let map = (fn, range) => {
|
|
|
130
106
|
}
|
|
131
107
|
result
|
|
132
108
|
}
|
|
109
|
+
|
|
110
|
+
provide module Inclusive {
|
|
111
|
+
/**
|
|
112
|
+
* Checks if the given number is within the range.
|
|
113
|
+
*
|
|
114
|
+
* @param value: The number being checked
|
|
115
|
+
* @param range: The range to check within
|
|
116
|
+
* @returns Whether or not the value is within range
|
|
117
|
+
*
|
|
118
|
+
* @example Range.Inclusive.inRange(1, { rangeStart: 0, rangeEnd: 1 }) == true
|
|
119
|
+
* @example Range.Inclusive.inRange(10, { rangeStart: 0, rangeEnd: 2 }) == false
|
|
120
|
+
*
|
|
121
|
+
* @since v0.6.0
|
|
122
|
+
* @history v0.3.0: Root APIs originally handled Inclusive & Exclusive variants
|
|
123
|
+
*/
|
|
124
|
+
provide let inRange = (value, range) => {
|
|
125
|
+
match (range) {
|
|
126
|
+
{ rangeStart: lower, rangeEnd: upper } when value >= lower &&
|
|
127
|
+
value <= upper => true,
|
|
128
|
+
{ rangeStart: upper, rangeEnd: lower } when value >= lower &&
|
|
129
|
+
value <= upper => true,
|
|
130
|
+
_ => false,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Calls the given function with each number in the range.
|
|
136
|
+
*
|
|
137
|
+
* For increasing ranges, the value is increased by `1` in each iteration,
|
|
138
|
+
* and for decreasing ranges, the value is decreased by `1`. The value is
|
|
139
|
+
* always changed by `1`, even if non-integer values were provided in the range.
|
|
140
|
+
*
|
|
141
|
+
* @param fn: The function to be executed on each number in the range
|
|
142
|
+
* @param range: The range to iterate
|
|
143
|
+
*
|
|
144
|
+
* @example Range.Inclusive.forEach(val => print(val), { rangeStart: 0, rangeEnd: 2 })
|
|
145
|
+
*
|
|
146
|
+
* @since v0.3.0
|
|
147
|
+
* @history v0.3.0: Root APIs originally handled Inclusive & Exclusive variants
|
|
148
|
+
*/
|
|
149
|
+
provide let forEach = (fn: Number => Void, range) => {
|
|
150
|
+
match (range) {
|
|
151
|
+
{ rangeStart: lower, rangeEnd: upper } when lower <= upper => {
|
|
152
|
+
let mut idx = lower
|
|
153
|
+
while (idx <= upper) {
|
|
154
|
+
fn(idx)
|
|
155
|
+
idx += 1
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{ rangeStart: upper, rangeEnd: lower } => {
|
|
159
|
+
let mut idx = upper
|
|
160
|
+
while (idx >= lower) {
|
|
161
|
+
fn(idx)
|
|
162
|
+
idx -= 1
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Produces a list by calling the given function on each number included in the range.
|
|
170
|
+
*
|
|
171
|
+
* For increasing ranges, the value is increased by `1` in each iteration,
|
|
172
|
+
* and for decreasing ranges, the value is decreased by `1`. The value is
|
|
173
|
+
* always changed by `1`, even if non-integer values were provided in the range.
|
|
174
|
+
*
|
|
175
|
+
* @param fn: The function called on each number in the range that returns the value for the output list
|
|
176
|
+
* @param range: The range to iterate
|
|
177
|
+
* @returns A list containing all values returned from the `fn`
|
|
178
|
+
*
|
|
179
|
+
* @example Range.Inclusive.map(val => val * 2, { rangeStart: 0, rangeEnd: 2 }) == [0, 2, 4]
|
|
180
|
+
*
|
|
181
|
+
* @since v0.3.2
|
|
182
|
+
* @history v0.3.0: Root APIs originally handled Inclusive & Exclusive variants
|
|
183
|
+
*/
|
|
184
|
+
provide let map = (fn, range) => {
|
|
185
|
+
let mut result = []
|
|
186
|
+
match (range) {
|
|
187
|
+
{ rangeStart: lower, rangeEnd: upper } when lower <= upper => {
|
|
188
|
+
let mut idx = upper
|
|
189
|
+
while (idx >= lower) {
|
|
190
|
+
result = [fn(idx), ...result]
|
|
191
|
+
idx -= 1
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{ rangeStart: upper, rangeEnd: lower } => {
|
|
195
|
+
let mut idx = lower
|
|
196
|
+
while (idx <= upper) {
|
|
197
|
+
result = [fn(idx), ...result]
|
|
198
|
+
idx += 1
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
result
|
|
203
|
+
}
|
|
204
|
+
}
|